char *ptr="Is memory allocated here?"
Author |
Message |
R Michael McMah #1 / 24
|
 char *ptr="Is memory allocated here?"
I have three questions regarding memory allocation: char *ptr="some stupid string"; char array[]="some stupid string"; First, when a char pointer is initialized with a string, is sufficient memory allocated? Aside from "ptr" being an lvalue, while "array" is only an rvalue, is there any other difference between "ptr" and "array"? void foo(char *ptr); // function prototype void main(void) { foo("literal string"); Quote: }
Second, what happens when a literal string is passed to a function expecting a char pointer? My best guess is that "literal string" goes on the stack, and "ptr" is initialized to the former stack base. Is this right? Last, I have written programs which (successfully) use free() to release calloc()'d memory (as opposed to using cfree() to release the memory). What are the differences between these two functions? I believe that calloc() is nearly identical to (and probably uses) malloc(), so is this practice really acceptable? Thanks alot.
|
Sat, 02 Apr 1994 23:05:47 GMT |
|
 |
P. Harris #2 / 24
|
 char *ptr="Is memory allocated here?"
Quote: >I have three questions regarding memory allocation: >char *ptr="some stupid string"; >char array[]="some stupid string"; >First, when a char pointer is initialized with a string, is sufficient >memory allocated? Aside from "ptr" being an lvalue, while "array" is >only an rvalue, is there any other difference between "ptr" and "array"? >void foo(char *ptr); // function prototype >void main(void) >{ > foo("literal string"); >} >Second, what happens when a literal string is passed to a function >expecting a char pointer? My best guess is that "literal string" >goes on the stack, and "ptr" is initialized to the former stack >base. Is this right?
Apart from when an array is initialised, all references to a string cause a static copy of that string to be stored somewhere in memory and the string in the source, er, sort of, replaced by a pointer to the first character of the string. So in your first example, the string is put somewhere [it doesn't matter where, but it generally wont get erased] and ptr is initialised with a pointer to the first character of the string, whereas for the array the individual elements of the array are intialised with the characters of your string. In the second, a STATIC copy of the string is stored at compile time somewhere in your program, and code is compiled to pass a pointer to the first character of "literal string" to foo(). Strings are not generally pushed on and off stacks, except when initialising auto (the default storage for local variables) character arrays in ANSI C. I hope that answers your question. If foo actually changes a character in your string, then the next time that actual statement is re-run, the revised string will be passed to foo(). Quote: >Last, I have written programs which (successfully) use free() to >release calloc()'d memory (as opposed to using cfree() to release >the memory). What are the differences between these two functions? >I believe that calloc() is nearly identical to (and probably uses) >malloc(), so is this practice really acceptable?
cfree() and free(): not much except that cfree() isn't in the ANSI library, so use free(). malloc() and calloc(): these are similar, malloc allocates bytes whereas calloc allocates units. malloc needs one parameter, being the number of bytes. calloc needs two: the size of each unit in bytes and the number of units. So if you wanted to allocate space for a [sorry, read 'char's, not 'byte's.] hundred chars, you'd write ptr = malloc(100) But if you wanted to allocate space for 100 long ints, you'd write: ptr = calloc(sizeof(long int), 100) I may have got the parameters the wrong way round for calloc(), but in practise it rarely matters as calloc usally looks like this: void /* or char in K&R C */ *calloc(us,no) int us,no; { return malloc(us*no); Quote: } >Thanks alot.
You're welcome.
Paul Harrison [Opinions are mine, not UEA's]
|
Sun, 03 Apr 1994 01:58:16 GMT |
|
 |
Terry Gardn #3 / 24
|
 char *ptr="Is memory allocated here?"
: I have three questions regarding memory allocation: : : : char *ptr="some stupid string"; : char array[]="some stupid string"; :
Related to this question is the old 'what happens if I have an array allocated in one file, and give an extern reference as a POINTER in another source file?' $ cat 1.c char array[1024]; $ cat 2.c extern char *array; file 2.c is incorrect. $ cat 2.a.c extern char array[]; is correct (assuming these 2 files are linked together). -- Terry Gardner | The Home Depot, Inc. | One Paces West 2727 Paces Ferry Road, NW | Atlanta, GA Voice (404)433-8211x5124
|
Sun, 03 Apr 1994 03:11:28 GMT |
|
 |
Jim Jagiels #4 / 24
|
 char *ptr="Is memory allocated here?"
Quote: >I have three questions regarding memory allocation: >char *ptr="some stupid string"; >char array[]="some stupid string"; >First, when a char pointer is initialized with a string, is sufficient >memory allocated? Aside from "ptr" being an lvalue, while "array" is >only an rvalue, is there any other difference between "ptr" and "array"?
The string in *ptr is constant and most/all compilers will create it as such. Thus, trying to write to it will be a Bad Thing. No such problems with array since it is "kept" in "writable" storage and can be altered at will (although if you write PAST the \0 after "string" Bad Things can happen). Quote: >void foo(char *ptr); // function prototype >void main(void) >{ > foo("literal string"); >} >Second, what happens when a literal string is passed to a function >expecting a char pointer? My best guess is that "literal string" >goes on the stack, and "ptr" is initialized to the former stack >base. Is this right?
What the compiler actually does is to pass a pointer to that literal string. In effect "a string" is a pointer to the string "a string". This makes sense when you consider: char *cptr; cptr = "hello"; since cptr is a char pointer, "hello" must be also... -- ============================================================================== #include <std/disclaimer.h> Jim Jagielski NASA/GSFC, Code 711.4
"Ah! I see you have the machine that goes 'BING!'"
|
Sun, 03 Apr 1994 01:01:49 GMT |
|
 |
Fabi #5 / 24
|
 char *ptr="Is memory allocated here?"
|> |> >I have three questions regarding memory allocation: (Questions deleted her, not really relevant to this posting) |> cfree() and free(): not much except that cfree() isn't in the ANSI |> library, so use free(). |> malloc() and calloc(): these are similar, malloc allocates bytes |> whereas calloc allocates units. malloc needs one parameter, being |> the number of bytes. calloc needs two: the size of each unit in |> bytes and the number of units. So if you wanted to allocate space |> for a [sorry, read 'char's, not 'byte's.] hundred chars, you'd |> write ptr = malloc(100) |> |> But if you wanted to allocate space for 100 long ints, you'd write: |> ptr = calloc(sizeof(long int), 100) Also, calloc is guaranteed to initialize the allocated space to all zeros, whereas malloc does not. (The 'c' standing for 'clear' ?) |> |> I may have got the parameters the wrong way round for calloc(), but |> in practise it rarely matters as calloc usally looks like this: Yes, reverse the order, ptr = calloc(100, sizeof(ling int)); |> void /* or char in K&R C */ *calloc(us,no) |> int us,no; |> { |> return malloc(us*no); |> } | More like void *calloc(size_t nobj, size_t size) { void *ptr; ptr = malloc(nobj * size); if(ptr) memset(ptr, 0, nobj * size); return ptr; Quote: }
|> Paul Harrison |> |> [Opinions are mine, not UEA's] Opinions are mine ? ------------------------------------------------------------
------------------------------------------------------------ "Ohm, sweet ohm" (Kraftwerk)
|
Sun, 03 Apr 1994 19:49:42 GMT |
|
 |
Warner Lo #6 / 24
|
 char *ptr="Is memory allocated here?"
Quote: (Sudheer Apte) writes: >Actually, it only initializes the space to zero *bytes*, not zero >int's or whatever. So calloc() really isn't much use for allocating >anything other than chars in practice. (K&R2, p.252).
You can count that you will get zero integers on almost all machines in the known universe (I know of none where this isn't true, but I'd like to know what the ones that you can't). However, you can't count on it making pointers have the same value as if the integer constant zero was assigned to them (or in other words, you can't count on the pointers in your struct being NULL pointers). THAT is what makes calloc less useful than you might first thing upon reading its description. Warner --
"Red hair is caused by sugar and lust," the woman, who was blond, confided. "Highly evolved beings do not indulge in sugar and lust." -- Tom Robbins
|
Mon, 04 Apr 1994 09:46:05 GMT |
|
 |
Sudheer Ap #7 / 24
|
 char *ptr="Is memory allocated here?"
Quote:
> Also, calloc is guaranteed to initialize the allocated space to all zeros, > whereas malloc does not. (The 'c' standing for 'clear' ?)
Actually, it only initializes the space to zero *bytes*, not zero int's or whatever. So calloc() really isn't much use for allocating anything other than chars in practice. (K&R2, p.252). Sudheer. ------------------ ...{harvard, uunet}!andrew.cmu.edu!sa1z
|
Mon, 04 Apr 1994 00:03:04 GMT |
|
 |
Jef Iwan #8 / 24
|
 char *ptr="Is memory allocated here?"
: I have three questions regarding memory allocation: : : : char *ptr="some stupid string"; : char array[]="some stupid string"; : : First, when a char pointer is initialized with a string, is sufficient : memory allocated? Aside from "ptr" being an lvalue, while "array" is : only an rvalue, is there any other difference between "ptr" and "array"? : : : void foo(char *ptr); // function prototype : : void main(void) : { : foo("literal string"); : } : : Second, what happens when a literal string is passed to a function : expecting a char pointer? My best guess is that "literal string" : goes on the stack, and "ptr" is initialized to the former stack : base. Is this right? : : Last, I have written programs which (successfully) use free() to : release calloc()'d memory (as opposed to using cfree() to release : the memory). What are the differences between these two functions? : I believe that calloc() is nearly identical to (and probably uses) : malloc(), so is this practice really acceptable? : : Thanks alot. :
In answer to your first question, most compilers should treat the two strings identically (although I have used some cross compilers which do not -- i.e. ASCII data gets pushed on the call stack instead of the address of the string...), and if they don't, then they (the compilers) are in error. When you use a string literal in a program, such as "some stupid string", the compiler will store that data within the program, so no space needs to be "allocated" per se; rather, that string has an address in the program's data space. Secondly, when you pass the literal string to a function expecting a char pointer, nothing as elaborate as you have hypothesized happens. The literal string (i.e. "literal string") will be put into the program's data space (as above) and the address to that data space will be passed to the function -- i.e. the function will get a char pointer to the area that the compiler put your literal string into. The thing to keep in mind is that unless your compiler is _VERY_ smart, each time you use a literal string space will be used for it in the progam's data space, even if the strings are the same. In other words, if your function calls foo("literal string") three different times, three separate instances of the string "literal string" will exist in your program's data space, and foo will get a different pointer value for each call. Finally, memory allocation schemes are machine dependent. However, in most schemes that I have seen, calloc() will call malloc, and then explicitly clear all of the bytes that you asked for. Since I am not familiar with cfree() (I think your compiler's libs may have some non-standard extensions...), I can't comment too generally on that. But, given that most calloc's operate in the manner that I have stated, then free() should work just fine. You may wish to use your compiler's option to produce assembly output in the future; this way, you can see exactly what the machine/program is doing. Of course, you could always use the #pragma dwim (do what I mean) :=) --------------------------------------------------------------------- -Jefrem M. Iwaniw, Sr. Consultant, Pelican Software 0 "To know even one life has breathed easier because _/ \ you have lived; This is to have succeeded." (_) -Ralph Waldo Emerson |_ My own opinions, not my clients'. ---------------------------------------------------------------------
|
Tue, 05 Apr 1994 21:04:08 GMT |
|
 |
Greg Huds #9 / 24
|
 char *ptr="Is memory allocated here?"
Bossman> malloc() and calloc() are similar, except that calloc() Bossman> actually clears the memory that is allocated to all zeros. Bossman> This is very useful for allocating arrays of NULL pointers.
RE> Actually, it's quite useless for doing that. All zeroes is not the RE> same as a NULL pointer. Well, if you accept K&R as an authority, you can assume that NULL is the integer 0 as far as the compiler is concerned. I'll quote gratuitously: K&R ed. 1 page 192: Quote: > ...it is guaranteed that assignment of the constant 0 to a > pointer will produce a null pointer distinguishable from a > pointer to any object.
K&R ed. 2 page 198 Quote: > An integral constant expression with value 0, or such an > expression cast to type void *, may be converted, by a cast, by > assignment, or by comparison, to a pointer of any type. This > produces a null pointer that is equal to another pointer of the > same type, but unequal to any pointer to a function or object.
This doesn't guarantee that the memory representation of this pointer is zero, but it seems the obvious implementation is to store null pointers just like the integer 0, i.e. as zeroed memory. While there are some who don't want to write code that assumes anything but what's specified in either K&R I or the ANSI standard, I think it's reasonable to initialize memory containing NULL pointers with a direct memory manipulation function if it's going to work on just about all the existing C compilers. Library functions and include files are much more likely to limit your code than obscure compiler implementation details, in my experience, which is admittedly limited to Unix and MessyDos systems. Of course, it's possible there are a few compilers floating around that don't store null pointers as zeroed memory. I'm interested in knowing if anyone out there finds one. #include <stdio.h> main() { char **p; p = (char **) calloc(1, sizeof(char *)); if (*p == NULL) { puts("Zeroed memory functions as NULL pointer."); } else { puts("Zeroed memory does not function as NULL pointer."); } Quote: }
Incidentally, I saw someone printf(str); recently. The specific example had str as "foo\n" after preprocessing, which will work, but in general, fputs(str, stdout); or printf("%s", str); is less likely to cause conflicts and slightly faster. Greg Hudson
|
Mon, 11 Apr 1994 11:56:43 GMT |
|
 |
Bossm #10 / 24
|
 char *ptr="Is memory allocated here?"
Quote: >char *ptr="some stupid string"; >char array[]="some stupid string"; >First, when a char pointer is initialized with a string, is sufficient >memory allocated? Aside from "ptr" being an lvalue, while "array" is >only an rvalue, is there any other difference between "ptr" and "array"?
Yes there is a difference between the first statement and the second one. FOr the first statement, the C compiler will allocate space for the string in a global pool of static string data. It then initialises 'ptr' to point to this string. The array version however actually creates an array in your global data segment (or on the stack) containing the data of the string. Quote: >void foo(char *ptr); // function prototype >void main(void) >{ > foo("literal string"); >} >Second, what happens when a literal string is passed to a function >expecting a char pointer? My best guess is that "literal string" >goes on the stack, and "ptr" is initialized to the former stack >base. Is this right?
No, this is incorrect. As in the first example, all literal string data is placed into a global string pool by the compiler (which resides in the same spot as your global variable data). It just passes a pointer to this literal string to the function. You have to be careful when using literal strings, since only enough space to hold all of the string's data and the null terminator are alloccated by the compiler, so if you attempt to concatenate another string to a literal string (or use any function that adds characters to the string), you will actually be overwriting other memory in your global data space. Thus if you wish to add something to the end of the string "some stupid string", you would have to do it like so: char array[255] = "some stupid string"; ... strcat(array," This is added!!"); Quote: >Last, I have written programs which (successfully) use free() to >release calloc()'d memory (as opposed to using cfree() to release >the memory). What are the differences between these two functions? >I believe that calloc() is nearly identical to (and probably uses) >malloc(), so is this practice really acceptable?
malloc() and calloc() are similar, except that calloc() actually clears the memory that is allocated to all zeros. This is very useful for allocating arrays of NULL pointers. Apart from this, the function the same, and yes, calloc() probably does call malloc(). Thus using free() to free the memory is quite alright. +------------------------------------------+----------------------------------+ | Kendall Bennett, | Internet: |
+------------------------------------------+----------------------------------+ | CoSysop (Bossman), PC Connection Australia: +61 3 688 0909 | +-----------------------------------------------------------------------------+
|
Sun, 10 Apr 1994 09:47:37 GMT |
|
 |
John Boutla #11 / 24
|
 char *ptr="Is memory allocated here?"
Quote:
> Bossman> malloc() and calloc() are similar, except that calloc() > Bossman> actually clears the memory that is allocated to all zeros. > Bossman> This is very useful for allocating arrays of NULL pointers. > Actually, it's quite useless for doing that. All zeroes is not the > same as a NULL pointer. > --
Is it really useless ? stdio.h normally defines NULL as 0. Surely all that would be needed would be an appropriate cast to the type of null pointer required. John Boutland.
|
Mon, 11 Apr 1994 12:40:49 GMT |
|
 |
Robert Ea #12 / 24
|
 char *ptr="Is memory allocated here?"
Bossman> malloc() and calloc() are similar, except that calloc() Bossman> actually clears the memory that is allocated to all zeros. Bossman> This is very useful for allocating arrays of NULL pointers. Actually, it's quite useless for doing that. All zeroes is not the same as a NULL pointer. --
|
Sun, 10 Apr 1994 18:31:27 GMT |
|
 |
Stephen D. Clama #13 / 24
|
 char *ptr="Is memory allocated here?"
Quote:
>> Actually, it's quite useless for doing that. All zeroes is not the >> same as a NULL pointer. >Is it really useless ? stdio.h normally defines NULL as 0. Surely all >that would be needed would be an appropriate cast to the type of >null pointer required.
This keeps coming up, although it is addressed in the FAQ. A null pointer might be represented by all bits zero, but it need not. When assigning or casting a constant zero to a pointer, the compiler is obligated to generate the correct representation for a null pointer of that type -- which might or might not be all bits zero. So, if T is a some type, /* p becomes a null pointer of type T* */ T* p = 0; /* p gets all bits zero, which might not be a null pointer */ T* p = calloc(1, sizeof(T*)); /* p gets all bits zero, which might not be a null pointer */ int i = 0; T* p = i; /* 'i' is not a constant zero */ --
|
Mon, 11 Apr 1994 23:54:45 GMT |
|
 |
Barry Margol #14 / 24
|
 char *ptr="Is memory allocated here?"
Quote: > /* p gets all bits zero, which might not be a null pointer */ > int i = 0; > T* p = i; /* 'i' is not a constant zero */
Actually, the contents of p are implementation-dependent in this case. The results of conversions between integer and pointer types are undefined, and aren't even required to return the original integer if the inverse conversion is later performed on the result. There's no rule that says that the bits of the integer are copied into the bits of the pointer. -- Barry Margolin, Thinking Machines Corp.
{uunet,harvard}!think!barmar
|
Tue, 12 Apr 1994 02:41:16 GMT |
|
 |
Paul Sm #15 / 24
|
 char *ptr="Is memory allocated here?"
Quote:
>Bossman> malloc() and calloc() are similar, except that calloc() >Bossman> actually clears the memory that is allocated to all zeros. >Bossman> This is very useful for allocating arrays of NULL pointers.
>RE> Actually, it's quite useless for doing that. All zeroes is not the >RE> same as a NULL pointer. >Well, if you accept K&R as an authority, you can assume that NULL >is the integer 0 as far as the compiler is concerned. I'll quote >gratuitously:
No, if you accept K&R as an authority, you can assume that a CONSTANT 0, that is, the ASCII character 0 appearing in the source code, will be turned into whatever representation is required for a null pointer in the object segment. And (from your second quote) that a CONSTANT expression with value 0 will be similarly converted by the compiler. Quote: >This doesn't guarantee that the memory representation of this >pointer is zero, but it seems the obvious implementation is to >store null pointers just like the integer 0, i.e. as zeroed >memory.
This may be 'obvious', but it is also WRONG, and assuming it will get you in trouble. I've used several machines in the recent past in which it is NOT true, and where assuming it will NOT work. The last time we had this discussion, other people listed even more machines than I'd have dreamed possible for which this will not work. If you do it, it will come back to haunt you. Quote: >Of course, it's possible there are a few compilers floating around >that don't store null pointers as zeroed memory. I'm interested in >knowing if anyone out there finds one.
There are LOTs of them.
|
Mon, 11 Apr 1994 23:53:40 GMT |
|
|
Page 1 of 2
|
[ 24 post ] |
|
Go to page:
[1]
[2] |
|