I know that calloc request memory to be used, writes 0 on all the bits and then returns a pointer to it.
My question is: if I use calloc with a structure that contains pointers, will those pointers have the NULL value or do I have to set them to point to NULL?
struct a{
char * name;
void * p;
}* A;
So basically, will name and p point to NULL after I've used calloc with struct a?
Thanks!
Somehow you've gotten a lot of incorrect answers. C does not require the representation of null pointers to be all-zero-bits. Many people mistakenly think it does, since an integer constant expression with value 0, converted to a pointer, becomes a null pointer.
With that said, on all real-world systems, null pointers are all-zero-bits, and calloc is a perfectly reasonable way to get a null-pointer-initialized pointer array in the real world.
R.'s answer is good, but I'd like to add the standard quotes to support this, and show a way to 0 initialize your struct that does, in fact, yield NULL pointers.
From N1548 (C11 draft)
7.22.3.2 The calloc function allocates space for an array of nmemb objects, each of whose size
is size. The space is initialized to all bits zero.[289]
The footnote then says (emphasis added):
Note that this need not be the same as the representation of floating-point zero or a null pointer constant.
While a null pointer is usually represented as all 0 bits, this representation is not guaranteed. To answer your question directly, no you cannot rely on the calloc()'d struct's pointers to be NULL.
If you want to set all contained pointers of a dynamically allocated struct to NULL you can use the following:
struct a *s = malloc(sizeof *s);
*s = (struct a){0};
C11:
6.7.9.21
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, [...] the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration
and
6.7.9.10
... If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
C requires you to have at least one element inside the braces, which is why I use {0} instead of {}. The rest of the elements are initialized according to the above rules, which results in null pointers. As far as I can tell, the rules for this are the same in C11 and C99.
The ISO C standard for calloc requires it to initialize everything to 0. That means that if you end up veiwing memory allocated by calloc as pointers, it will indeed initially contain NULL (0) pointers.
Related
I hope not to sound very foolish here, but does the NULL module actually require memory allocation or not when doing this:
TheNull = malloc(sizeof(NULL));
If true, how can something that has no memory allocated actually exist in the ram?
If you use NULL as parameter of malloc(sizeof()), does it return NULL?
No, unless out-of-memory, like any other allocation.
NULL, the null pointer constant, does not have a particular type. It may be void *, int, long, or some integer type.
Avoid sizeof(NULL) as its size/type may differ from system to system.
The expression is not in any other way related to any NULL module or NULL object. There are no such things anyway.
NULL is just a useful definition for a null pointer constant.
The C Standard specifies the NULL macro defined in <stddef.h> and some other standard headers this way:
7.19 Common definitions <stddef.h>[...]
The macros are [...]
NULL
which expands to an implementation-defined null pointer constant [...]
null pointer constant is defined in 6.3.2.3:
6.3.2.3 Pointers[...]3. An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.67) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
67) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19.
Many targets define NULL is defined as #define NULL ((void *)0), while other targets just use #define NULL 0, or possibly some other zero integer constant expression (eg: 0L, 0UL...).
Hence malloc(sizeof(NULL)) attempts to allocate the number of bytes corresponding to the type of the expression in the definition of NULL, probably the size of void pointer, but never 0 bytes.
Whether it succeeds or not depends on available memory:
if successful, the return value will be a valid pointer, different from NULL.
if malloc(sizeof(NULL)); does return NULL, it means no memory is available to allocate a very small size, a critical situation that should be reported to the user and handled with care.
TheNull = malloc(sizeof(NULL));
That doesn't allocate 0 bytes (because sizeof(NULL) isn't zero), but malloc(0) might. The standard says:
If size is zero, the behavior of malloc is implementation-defined. For
example, a null pointer may be returned. Alternatively, a non-null
pointer may be returned; but such a pointer should not be
dereferenced, and should be passed to free to avoid memory leaks.
So, maybe a null pointer, maybe not.
If true, how can something that has no memory allocated actually exist in the ram?
The pointer returned from malloc might point to a piece of memory slightly larger than what you asked for. For example, if you ask for 1 or 2 bytes, you might get 8 (or even 16) bytes instead. A memory manager often only provides certain size memory blocks (for efficiency), and might require a minimum size so its own bookkeping can fit in a free'd block.
And if it returns an oversized block for 1 or 2 bytes, it could do that for 0 bytes as well.
I've read that the difference between calloc and malloc is that calloc initializes the memory to the default value of the type declared.
For struct, what is the default value?
Is there a difference between using calloc and malloc for dynamic array of struct?
Would the members of the struct also be initialized?
calloc() will initialize the entire allocated memory range to zero. It has nothing to do with what type you are casting to.
malloc() leaves the contents of the memory in an unspecified state.
The calloc function does not initialize memory to the default value for a given type, and in fact it can't because it knows nothing regarding the type that the memory will be used for.
What it does do is set the memory to all bits 0. On most implementations you're likely to come across, this means that integer and floating point types will have the value 0 and that pointer types will be NULL. With regard to structs and/or arrays, this would apply to any members, and additionally any padding within a struct would also have all bits set to 0.
Here consider the following sample of code:
int *a = malloc(sizeof(int) * n);
Can this code be used to define an array a containing n integers?
int *a = malloc(sizeof(int) * n);
Can this code be used to define an array a containing n integers?
That depends on what you mean by "define an array".
A declaration like:
int arr[10];
defines a named array object. Your pointer declaration and initialization does not.
However, the malloc call (if it succeeds and returns a non-NULL result, and if n > 0) will create an anonymous array object at run time.
But it does not "define an array a". a is the name of a pointer object. Given that the malloc call succeeds, a will point to the initial element of an array object, but it is not itself an array.
Note that, since the array object is anonymous, there's nothing to which you can apply sizeof, and no way to retrieve the size of the array object from the pointer. If you need to know how big the array is, you'll need to keep track of it yourself.
(Some of the comments suggest that the malloc call allocates memory that can hold n integer objects, but not an array. If that were the case, then you wouldn't be able to access the elements of the created array object. See N1570 6.5.6p8 for the definition of pointer addition, and 7.22.3p1 for the description of how a malloc call can create an accessible array.)
int *a = malloc(sizeof(int) * n);
Assuming malloc() call succeeds, you can use the pointer a like an array using the array notation (e.g. a[0] = 5;). But a is not an array itself; it's just a pointer to an int (and it may be a block of memory which can store multiple ints).
Your comment
But I can use an array a in my program with no declaration otherwise
suggests this is what you are mainly asking about.
In C language,
p[i] == *(p + i) == *(i + p) == i[p]
as long as one of i or p is of pointer type (p can an array as well -- as it'd be converted into a pointer in any expression). Hence, you'd able to index a like you'd access an array. But a is actually a pointer.
Yes. That is exactly what malloc() does.
The important distinction is that
int array[10];
declares array as an array object with enough room for 10 integers. In contrast, the following:
int *pointer;
declares pointer as a single pointer object.
It is important to distiguinsh that one of them is a pointer and that the other as an actual array, and that arrays and pointers are closely related but are different things. However, saying that there is no array in the following is also incorrect:
pointer = malloc(sizeof (int) * 10);
Because what this piece of code does is precisely to allocate an array object with room for 10 integers. The pointer pointer contains the address of the first element of that array.(C99 draft, section 7.20.3 "Memory management functions")
Interpreting your question very literally, the answer is No: To "define an array" means something quite specific; an array definition looks something like:
int a[10];
Whereas what you have posted is a memory allocation. It allocates a space suitable for holding an array of 10 int values, and stores a pointer to the first element within this space - but it doesn't define an array; it allocates one.
With that said, you can use the array element access operator, [], in either case. For instance the following code snippets are legal:
int a[10];
for (int i = 0; i < 10; i++) a[i] = 0;
and
int *a = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) a[i] = 0;
There is a subtle difference between what they do however. The first defines an array, and sets all its elements to 0. The second allocates storage which can hold an equivalently-typed array value, and uses it for this purpose by initialising each element to 0.
It is worth pointing out that the second example does not check for an allocation error, which is generally considered bad practice. Also, it constitutes a potential memory leak if the allocated storage is not later freed.
In the language the Standard was written to describe (as distinct from the language that would be described by a pedantic literal reading of it), the intention was that malloc(n) would return a pointer that would, if cast to a T*, could be treated as a pointer to the first element of a T[n/sizeof T*]. Per N1570 7.22.3:
The
pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to
a pointer to any type of object with a fundamental alignment requirement and then used
to access such an object or an array of such objects in the space allocated (until the space
is explicitly deallocated).
The definition of pointer addition and subtraction, however, do not speak of acting upon pointers that are "suitably aligned" to allow access to arrays of objects, but rather speak of pointers to elements of actual array objects. If a program accesses space for 20 int objects, I don't think the Standard does actually says that the resulting pointer would behave in all respects as though it were a pointer to element [0] of an int[20], as distinct from e.g. a pointer to element [0][0] of an int[4][5]. An implementation would have to be really obtuse not to allow it to be used as either, of course, but I don't think the Standard actually requires such treatment.
In C, when I declare an array:
char MyArray[100] = { 0 };
What is the value inserted into the array's elements?
Is it possible to fill it with NULLs?
In this case, all elements will be initialized with null character '\0'.
C11-§6.7.9/21:
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
and paragraph 10 says that
[...] If an object that has static or thread storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
Is it possible to fill it with NULLs?
NULL is a macro which is used for null pointers and not for null characters.
In the declaration
char MyArray[100] = { 0 };
all elements are initialized to zero. Filling it with NULL:s makes no real sense, however you can use the character constant '\0' if that is what you mean.
In C the preprocessor macro NULL is defined (by several headers, including <stdio.h> and <stddef.h>) as a null pointer constant, typically 0 or ((void *)0).
So basically you can only initialize values to 0 (or \0 for char) which your code is doing for the entire array, NULL has a different purpose - its not the same as null in other languages like C# or Java.
Even if you wrote:
char MyArray[100] = { 65 };
The remaining elements will be initialized to 0 by the Compiler.
NULL should be used only as a pointer constant
In this case, all the memory attributable to the array is set to \0.
This is true in general with the exception of pointers which are initialised to the null pointer value (which might be 0 but the C standard does not insist on that).
Note that the NULL of C does not denote a null reference value as it does in other languages such as Java.
Compiler set default value for omitted array elements. The compiler that reserves the 100 zero bytes in the data segement of the program.
You initialized all elements of your array with the value 0, this is what = { 0 } stands for in an initialization expression.
Filling with NULL is non-sense as NULL is value defined for pointers and your array is an array of chars not pointer to something.
Maybe what you would like is to set the value to something that would mean not defined yet, but this does not exists in C. Every variable, at the time, it is defined, as a value. NULL doesn't mean no value, but does not point to something; but it is a value!
Before putting my question, I want to quote "Expert C Programming" [Page :276, last paragraph]:
"The beauty of Illiffe vector data structre is that it allows arbitrary arrays of pointers to strings to be passed to functions, but only arrays of pointers, and only pointers to strings.
This is because both strings and pointers have the convention of an explicit out-of-bound value(NUL and NULL, respectively) that can be used as an end marker."
So, What I understood from above text is that if there is an array of pointers they have explicit out-of-bound value like NULL.( Correct me , if I'm wrong...)
So, it left me wondering what are the default values of an array of pointers(thinking that an array of pointers would have last pointer as NULL). Tried below code-snippets and result was very different.
int *x[2];
printf("%p %p",x[0],x[1]);
Output is: (nil) 0x400410
int *x[3];
printf("%p %p %p",x[0],x[1],x[2]);
Output is: 0xf0b2ff 0x400680 (nil)
int *x[4];
printf("%p %p %p %p", x[0],x[1],x[2],x[3]);
Output is: (nil) 0x4003db 0x7fffe48e4776 0x4006c5
So, with the above outputs , it is clear that there is an explicit Out-of-Bound (nil) value assigned to one of the pointers(one pointer is NIL), but is it truly the end-marker? No.
Is it one of those "Implementation defined" things of C-language?
I'm using a GCC compiler(4.6.3) on a Ubuntu machine.
Is it one of those "Implementation defined" things of C-language?
No, that's not implementation-defined - it's plain "undefined". The same is true for arrays of all types: the values that you see in them are undefined until explicitly initialized.
What I understood from above text is that if there is an array of pointers they have explicit out-of-bound value like NULL.
The author wanted to say that there is a value (specifically, NULL value) that can be used to mark a "no value" in an array of pointer. The author did not mean to imply that such a no-value marker would be placed into an array of pointers by default.
An array, or any object, with automatic storage duration (i.e., any object defined within a function body without the static keyword) has no default initial value unless you specify one. Its initial value is garbage, and you must not access that value before assigning something to it.
An object with static storage duration (i.e., any object defined outside any function and/or with the static keyword) is initialized to zero, with the meaning of "zero" (0 for integers, 0.0 for floating-point, null for pointers) applied recursively to subobjects.
You can use an initializer to ensure that a pointer object is set to a null pointer, or to whatever value you like:
int *x[2] = { NULL, NULL };
or, more simply:
int *x[2] = { 0 }; /* sets first element to 0, which is converted to a null
pointer; other elements are implicitly set to null
pointers as well */
You are misreading the quotation from "Expert C Programming." The key phrase there is the following:
This is because both strings and pointers have the *convention* of an explicit
out-of-bound value (NUL and NULL, respectively).
It is possible and even conventional to have an array of strings such that the last pointer is set to NULL. This can allow one to iterate over the array quite easily without knowing exactly how many elements there are in the array:
char* dwarves[] = { "Dopey",
"Grumpy",
"Sleepy",
"Happy",
"Sneezy",
"Bashful",
"Doc",
NULL
};
But you have to explicitly set the last pointer to NULL. Such structures are useful because they allow elegant code. So if you want to print or otherwise manipulate the array, you don't need to worry about how many strings are in it, as the NULL pointer will signal the end:
for (char** pWalk = dwarves; *pWalk; pWalk++)
printf ("%s\n", *pWalk);
The beauty of this particular type of ragged-array structure is that strings by definition have a built-in NUL terminator, and the array of pointers is terminated with the NULL, so the endpoints of both dimensions are known. However, the NULL as the last pointer in the array is not something that's built into the language. It has to be explicitly set. Failing to do so would be the equivalent of declaring an array of char but not terminating it with a NUL:
char myString[] = { 'H', 'e', 'l', 'l', 'o' } // No NUL termination
Just as you would have to know how many characters there are in this array if you want to manipulate it in any useful way, without the NULL at the end of the array of pointers, manipulating it would be more difficult.
That's really all that Peter van der Linden is saying in the paragraph you quoted about Illiffe data structures.
There is no requirement in C that any local variable should have any 'default' value. So, when the compiler reserves two (or three) memory locations, the initial value is whatever that these memory locations contained before - there will not be any default initialization.
Unless your array was declared at file scope (outside of any function) or with the static keyword, the array contents will not be initialized; each element will contain some random bit pattern that may or may not correspond to a valid address.
If your array was declared at file scope or with the static keyword, then each element would be implicitly initialized to NULL. Note that attempting to dereference a NULL pointer results in undefined behavior, so you will want to check that your pointer isn't NULL before doing something with it.
A null pointer represents a well-defined "nowhere", guaranteed to compare unequal to any valid memory address. Note that there is a null pointer constant1 and a null pointer value2, and the two are not necessarily the same. In your source code, the macro NULL is set to the null pointer constant. During translation, each occurence of NULL in your source code is replaced with the real null pointer value.
There are invalid pointer values other than NULL; it's just that NULL is well-defined and works the same everywhere.
1. Any 0-valued integral expression, as used in a pointer context. Could be a naked 0, or (void *) 0, or something else that evaluates to 0.
2. Value used by the platform to represent a null pointer, which does not have to be 0.