Yes I did read these two posts.

http://stackoverflow.com/questions/3082914/c-compile-error-variable-sized-object-may-not-be-initialized
http://stackoverflow.com/questions/14186879/c-error-variable-sized-object-may-not-be-initialized

My case is a bit different because I'm using char * ptr[buflen]. This is what I have tried:

char  *ptr[buflen] = {0};  //This gave me the variable sized object error. 

char  *ptr[buflen];
memset( ptr, 0, buflen*buflen*sizeof(char)); //I figured this would work with looking at the previous examples. 

//This seemed to work but I am curious if I need to use free or malloc
after looking at the previous examples. I don't want this to seg fault later
in the program and have no clue what is causing it. 
char  *ptr[buflen]; 
memset(ptr, 0, sizeof ptr);

char *strings_line_tokens[503] = {0}; //Why does this work but the above won't work? 

Recommended Answers

All 2 Replies

Member Avatar for Blake_2

This has to do with what is known at compile time in C. Unless you are using C99 or C++, char *ptr[bufflen] won't compile. In C89/90, the array size must be a compile time constant, meaning that it is either a number or a macro like so:

#define BUFF_LEN 20

// in funcion or global scope
char *ptr_array[20];
char *ptr_array[BUFF_LEN];

If you are writing C89/90, your code is compiling due to a compiler extension. I'm not sure of the rationale behind not allowing VLA (variable length array) initializers, but, since it is only allowed as a compiler extension in C89, all you need to know is the compiler doesn't like it. As for char *strings_line_tokens[503] = {0};, this is standard C code (as far as I know). As a side note, if you write this at global scope, it gets 0 initialized for you, so you dont need the = {0} part.

The work aroung for this is malloc/calloc. Before I go further, I want to make sure you know what you are allocating. char *ptr[20]; is an array of 20 pointers to char. Thus, its size is sizeof(char*)*20 not buflen*buflen*sizeof(char). Since you seem to want to initialize your array with zeros, you should consider using calloc instead of malloc, as it will do it for you:

char *ptrs = (char*)calloc(bufflen, sizeof(char*));
/* use it */
free(ptrs); /* free it */

Calloc takes the number of things you want to allocate as its first parameter and the size of each individual thing as its second one.
For learning purposes, here is what it would look like if you were to initialize it manually:

char *ptrs = (char*)malloc(bufflen * sizeof(char*));
memset(ptrs, 0, bufflen * sizeof(char*));
/* use it */
free(ptrs); /* free it */

If you are intentionally using VLAs (either through an extension or with C99/C++), you could use memset on it the same way:

char* ptrs[bufflen];
/* Since, "ptrs" is an array (not a pointer), sizeof(ptrs) is the same as sizeof(bufflen * sizeof(char*)) */
memset(ptrs, 0, sizeof(ptrs)); 
/* no need to free "ptrs" */

The only difference is that you are using an array on the stack, so you don't have to free it. You do, however, have to free the pointers you get from malloc and calloc, as they are on the heap. Keep in mind, though, that if you store any pointers in your array that point to memory on the heap, you will need to keep track of those pointers ouside of the function or free them before the function returns. Otherwise, you will leak memory.

The last thing I want to mention is that in char *ptrs[20]; "ptrs" is an array while inchar* ptrs = (char*)calloc(20, sizeof(char*)); "ptrs" is a pointer that points TO an array on the heap. Thus, sizeof(ptrs) will evaluate to 20*sizeof(char*) in the array version and sizeof(char*) in the calloc version.

I hope this helped!

commented: Skilled +15

I'm not sure of the rationale behind not allowing VLA (variable length array) initializers

It's a combination of not complicating the compiler and not hiding an extremely volatile runtime task behind benign syntax. Even in C99+, VLAs are risky and not something I'd recommend using. Robust code shouldn't use them, as failure to allocate cannot be recovered from. A solid solution would still use the gamut of VLA, static array, and dynamic array, so cutting out the VLA part would actually simplify code.

you should consider using calloc instead of malloc

I'm torn between saying "no" and "hell no". The problem here is that an array of pointers is being allocated, and calloc encourages a false sense of security that those pointers are initialized to NULL. NULL need not be synonymous with all bits zero, which is what calloc does.

Otherwise, kudos for a good post. You get my upvote. :)

commented: How do I edit my post on here? I see a major typo and I want to include the calloc thing you mentioned; I wasn't aware of that! +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.