I have the following code:
struct stest
{
int x;
unsigned char data[];
} x =
{
1, {"\x10\x20\x30\x00\x10"}
};
int main()
{
printf( "x.data: %d\n", (int)x.data[0] );
return 0;
}
Which works fine. However, I need to use the size of the "data".
If I do:
printf( "sizeof x.data: %d\n", (int)sizeof(x.data) );
I get the error:
invalid application of ‘sizeof’ to incomplete type ‘char[]’
Is there a way to get the size of "data" in this situation, or maybe a suggestion of an alternative method I could use?
The compiler I am using is gcc 4.6.3.
Since x.data is a null terminated char array you could just use strlen function.
printf( "sizeof x.data: %u\n", strlen(x.data)+1 );
This code will not work correctly if the array contains null. In this case you need to store length of the array in separate member of struct.
As others have said, strlen will get you what you want.
The reason you're running into trouble isn't due to the string literal aspect, but rather the lack of a definite size of the array in your struct. It's an incomplete type. The compiler doesn't know how big the array is, and so sizeof can't figure it out.
Specifically, this is a "flexible array member". C99 added these. Structs with array's with an incomplete array as the last element (so it has room to grow).
Sizeof gets the size of the datatype.
Sizeof when applied to arrays, gets the size of the whole array.
Sizeof when applied to structs with a flexible array member, ignores the array.
Sizeof when applied to incomplete types simply fails. It gives up trying to figure out how big the array is.
So long story short, slap a number in your array. (Or pass along that information)
struct
{
int x;
int thesizeofmyarrayisfive = 5;
unsigned char data[5];
}
Add a size field to the structure.
#define DATA ("\x10\x20\x30\x00\x10")
struct stest
{
int x;
size_t size;
unsigned char data[];
} x =
{
1, sizeof DATA, { DATA }
};
There's only two options:
Store a terminating byte. Often people use the null character for this. Of course, you must make sure that the terminating byte is not found in the valid data part of the array.
Add a length member to your struct.
Related
I am working to create a set of functions in C that will allow a dynamically growing array. In this example I have create a struct with a variable titled len that stores the active length of the array, another variable titled size that stores the total length of the array assigned during initialization, and another variable titled array which is a pointer to the memory containing the array data. In this example the variable array is initialized in the struct as an integer. Within the function titled int_array I initialize the array and and return the struct. Within that function I call the init_int_array function that does the heavy lifting. In addition, I have another function titled append_int_array that checks the memory allocation and assigns another chunk of memory if necessary and then appends the array with a new index/variable. As you can see, this example is hard coded for an integer, and I will need to repeat these lines of code for every other data type if I want an array to contain that type of data. There has got to be a way to instantiate the struct so that the variable array can be a different data type so that I do not have to repeat all lines of code for every data type, but I am not sure what that method is. Any help would be appreciated. The code is shown below. NOTE: I also have a function to free the array memory after use, but I am omitting it since it is not relevant to the question.
array.h
#ifndef ARRAY_H
#define ARRAY_H
#include<stdlib.h>
#include<stdio.h>
typedef struc
{
int *array;
size_t len;
size_t size;
}Array;
void init_int_array(Array, size_t num_indices);
Array int_array(size_t num_indices);
void append_int_array(Array *array, int item);
#endif /* ARRAY_H */
Array.c
void init_int_array(Array *array, size_t num_indices) {
/* This function initializes the array with a guess for
the total array size (i.e. num_indices)
*/
int *int_pointer;
int_pointer = (int *)malloc(num_indices * sizeof(int));
if (int_pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
free(int_pointer);
exit(0);
}
else {
array->array = int_pointer;
array->len = 0;
array->size = num_indices;
}
}
Array int_array(size_t num_indices) {
/* This function calls init_int_array to initialize
the array and returns a struct containing the array
*/
Array array;
init_int_array(&array, num_indices);
return array;
}
void append_int_array(Array *array, int item) {
/* This function adds a data point/index to the array
and also doubles the memory allocation if necessary
to incorporate the new data point.
*/
array->len++;
if (array->len == array->size){
array->size *= 2;
int *int_pointer;
int_pointer = (int *)realloc(array->array, array->size * sizeof(int));
if (int_pointer == NULL) {
printf("Unable to reallocate memory, exiting.\n");
free(int_pointer);
exit(0);
}
else {
array->array = int_pointer;
array->array[array->len - 1] = item;
}
}
else
array->array[array->len - 1] = item;
}
A simple solution is rewrite your header like this:
typedef struct
{
void *array; // buffer
size_t len; // amount used
size_t elem; // size of element
size_t size; // size of buffer
} Array;
void init_array(Array *, size_t num_indices, size_t elem);
Array array(size_t num_indices, size_t elem);
void append_array(Array *array, void *item);
The changes to your code would be as follows:
Remove references to int in the name.
Make all inputs be to arbitrary type using void *.
Use array.elem instead of sizeof(int).
The biggest change is that elements to append will be passed by pointer, not by value.
Cast the buffer to whatever type you need to access elements.
Cast the buffer to char * internally to do pointer math on it.
Here is a sample calling sequence you could use:
Array buf = array(10, sizeof(int));
for(int i = 0; i < 3; i++) {
append_array(&buf, &i); // Remember that buf knows sizeof(int)
}
printf("Second element (of %d) is %d\n", buf->len, ((int *)buf->array)[1]);
C is a strongly- and statically-typed language without polymorphism, so in fact no, there is no language-supported form of dynamic typing. Every object you declare, every function parameter, every struct and union member, every array element has a specific type declared in your source code.
Some of the things you can do:
use a typedef or a preprocessor macro to provide indirection of the data type in question. That would allow you to have (lexically) one structure type and one set of support functions that provide for your dynamically-adjustable array to have any one element type of the user's choice, per program.
use preprocessor macros to template the structure type and support functions so that users can get separate versions for any and all element types they want. This might be usefully combined with _Generic selection.
define and use a union type for use as the array's element type, allowing use of any of the union's members' types. With a little more work, this can be made a tagged union, so that objects of different types in the same array could be supported. The cost, however, is wasted space and worse memory efficiency when you use members having smaller types.
use void * or maybe uintmax_t or unsigned char[some_largish_number] as the element type, and implement conversions to and from that type. This has some of the disadvantages of the union alternative, plus some complications surrounding the needed conversions. Also, there is no type that can be guaranteed large enough to accommodate all other data types. Nor even all built-in data types, though this is a more realistic goal.
use void as the formal element type (possible only with dynamic allocation and pointers, not with an array-style declaration). Add a separate member that recoirds the actual size of the elements. Implement wrappers / conversions that support use of that underlying structure in conjunction with various complete data types. This is described in more detail in another answer.
First, I have a struct here:
//Space to store the results for analysis map
struct Analysis analysis_space[32];
Each element of analysis_space array is for one file to store the results by some calculations;
So, my question is
If I want to get the size of each one of analysis_space,
It should be sizeof(analysis_space[0]) which returns the size of each element.
And sizeof(analysis_space) returns the whole array size?
Additional question:
Since analysis_space is an array, I suppose to initialize it before I store results into it?
Something like: analysis_space[0] = '\0' ?
... to get the size of each one of analysis_space, It should be sizeof(analysis_space[0]) which returns the size of each element.
sizeof(analysis_space[0]) returns the value of the char size of analysis_space[0]. The type returned is size_t and the matching printf() specifier is "%zu", "%zX" and others. When using the sizeof operator, code needs to use () with types. () are optional with objects.
printf("One element size %zu\n", sizeof analysis_space[0]);
And sizeof(analysis_space) returns the whole array size?
Yes,
printf("Array size %zu\n", sizeof analysis_space);
I suppose to initialize it before I store results into it? Something like: analysis_space[0] = '\0' ?
analysis_space[0] = '\0' is an assignment, not initialization. Further, struct Analysis expects a structure assignment/initialization, not scalar. Initialization is not required before writing
to it. #pm100
struct Analysis {
int a;
double b;
};
// Sample initialization
struct Analysis analysis_space[32] = {
{0, 0.0}, {1, 1.0} , {2, 2.0} }; // remainder zero initialized.
To compute the array element count:
// the type of the quotient is size_t
#define analysis_space_N (sizeof analysis_space / sizeof analysis_space[0])
I am new to C, and things are different in C than in any other language I've learned. In my homework I want to create an array of chars which point to an array of chars, but rather than make a multidimensional char array, I figure I'd have more control and create char arrays and put each individual one into the indexes of the original char array:
char keywords[10];
keywords[0] = "float";
The above example is to clarify and a simple case. But my question is due to the research I've been doing, and I am confused about something. Normally this would work in other languages, but in C it would be:
char *keyword[10];
keywords[0] = "float";
But when I want to send it through a function, why is this necessary:
void function(char **keyword); //function prototype
Wouldn't just passing the array pointer be enough?
It looks like you're confused by the double stars in
void function(char ** keyword);
The double stars just means that this function expects you to pass a pointer to a pointer to a char. This syntax doesn't include any information about the fact that you are using an array, or that the char is actually the first char of many in a string. It's up to you as the programmer to know what kind of data structure this char ** actually points to.
For example, let's suppose the beginning of your array is stored at address 0x1000. The keyword argument to the function should have a value of 0x1000. If you dereference keyword, you get the first entry in the array, which is a char * that points to the first char in the string "float". If you dereference the char *, you get the char "f".
The (contrived) code for that would look like:
void function(char **keyword)
{
char * first_string = *keyword; // *keyword is equivalent to keyword[0]
char first_char = *first_string; // *first_string is equivalent to first_string[0]
}
There were two pointers in the example above. By adding an offset to the first pointer before dereferencing it, you can access different strings in the array. By adding an offset to the second pointer before dereferencing it, you can access different chars in the string.
char *keyword[10];
keyword is an array 10 of char *. In a value context, it converted to a pointer to a char *.
This conversion is a part of what Chris Torek calls "The Rule":
"As noted elsewhere, C has a very important rule about arrays and pointers. This rule -- The Rule -- says that, in a value context, an object of type ‘array of T’ becomes a value of type ‘pointer to T’, pointing to the first element of that array"
See here for more information: http://web.torek.net/torek/c/pa.html
The C-FAQ also has an entry on this array to pointer conversion:
Question 6.3: So what is meant by the "equivalence of pointers and arrays'' in C?
http://c-faq.com/aryptr/aryptrequiv.html
In C, you can't really pass array to a function. Instead, you pass a pointer to the beginning of the array. Since you have array of char*, the function will get a pointer to char*, which is char**.
If you want, you can write (in the prototype) char *keyword[] instead of char **keyword. The compiler will automatically convert it.
Also, in C you can dereference pointers like arrays, so you loose almost nothing with that "converting to pointer".
If you want to
void function(char **keyword);
Andy, think about that an array is just a pointer(to the beginning of the array), that's why you write:
void function(char **keyword);
Because you have create an array to char pointers.
If it's easier to understand try:
void function(char *keyword[]);
But it's more C standard to use the first one, though if you use a C++ compiler won't really matter.
Here is the answer.
#include<stdio.h>
int main(void)
{
char *CharPtr[3];
char a[4]="abc";
char b[4]="def";
char c[4]="ghi";
CharPtr[0]=a;
CharPtr[1]=b;
CharPtr[2]=c;
printf("\n content of CharPtr[0] =%s",CharPtr[0]);
printf("\n content of CharPtr[1] =%s",CharPtr[1]);
printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
printf(" \n content of char a[4]=%s",a);
printf(" \n content of char b[4]=%s",b);
printf(" \n content of char c[4]=%s\n",c);
}
char *keywords[10] is an array of character pointers. So keywords[0], keywords[1].. and so on will have the addresses to different character arrays.
In printf you can use %s and keywords[0] to print the entire character array whose address(i.e. address of the first byte in the array) is stored at keywords[0].
While passing to a function, if you give *keywords, you are referring to the value at(address stored at keywords[0]) which is again an address. So, to get the value instead of address, you can add another *... Hope that clarifies a bit..
I am assuming that you are assigning your first string:
"float"
to the first index position of keyword[0]
char keyword[0] = "float";
which is the first index position of the array:
char keyword[10];
If the previous is the case, then in a sense, you are essentially creating a data structure that holds a data structure. The array of any type is the 'smallest' data structure of that type in C. Considering that in your example you are creating a character array, then you are actually utilizing the smallest data type (char=1bit) at each index position of the smallest built in data structure (the array).
With that said, if in your example, you are attempting to create an array of arrays; your character array
/* Hold ten characters total */
char keyword[10];
was designed to hold 10 characters. One at each index position (which you probably already know). So after declaring the array titled keyword, you then try to initialize the first index position of the array with another (the second) character array:
/* I believe this is what you had stated */
char keywords[0] = "float";
With the second character array having an index of 5 positions in size.
In order to achieve your desired goal, you would essentially be creating an array that basically emulates the effect of a data structure that 'holds' other data structures.
NOTE: If you had/have plans on trying to create a data structure that holds a data structure that holds a data structure. A.K.A. a triple nested data structure and in this case I think that would be a Matrix, WHICH I WOULDN'T RECOMMEND!
None the less, the matrix structure would be in the form of the first index position of keyword, being assigned the whole array of keywords, which would include all of the data stored in each index position of the keywords array. Then there would something probably like: keywords1, keywords2, ... keywords9,
which would essentially emulate the form of:
char *keyword[10] = {
char *keywords0[10] = {"float", etc, etc, etc.};
char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.};
and so
};
So basically from right to left, the keyword array, is an array of pointers that points to array of pointers that points to character arrays.
If that is what you are representing you would be better defining a custom data type of struct/record, and with in that custom structure you would want to define a subordinate or child level of structures. You could also pre-declare them then initialize them.
e.g.
typedef *nestedDataStructures {
struct keyWords[];
struct keyWords1[];
struct keyWords2[];
... and so on.
}; nestedDataStructures
Instead of adding ten structs to one custom structure I would break down into 3 or 4 (how ever many structures and use) and create a module in order to yield symmetrical layers of abstraction as you manipulate your data set.
None the less, you can not create the character array and potentially assign the other character array in the fashion that you did (or who knows maybe you can), but the way you would want to emulate the array that holds arrays, is to create a character pointer array up front, of X number index positions and then initialize then use the character arrays in the form of a strings declared with in the initialization of the original declaration.
So basically you could declare your whole array upfront, then with in your program design, either dereference each index position, use assignment, or print/write the index position.
Like for instance you could always do something like this:
/* Example of the program and declaration with out a function */
#include <stdio.h>
int main(){
/*
* A character pointer array that contains multiple
* character arrays.
*/
char *grewMe[2] = {"I want to ", "grow to be bigger"};
int w = 0;
for(; w < 2;) {
printf("%s", grewMe[w]);
++w;
}
printf(" :-)\n");
w = 0;
return 0;
}
// Output:
// I want to grow to be bigger :-)
Or something like this:
/* Example of program: function passed arguments
* of a pointer to the array of pointers
*/
#include <stdio.h>
void mygrowth(char *growMe[]);
int main(){
char *growMe[2] = {"I want to ", "grow to be bigger"};
mygrowth(growMe);
printf(" :-)\n");
return 0;
}
void mygrowth(char *growMe[])
{
int w = 0;
for (; w < 2;) {
printf("%s", growMe[w]);
++w;
}
}
The assignment of each index position as it's passed as an argument:
/*
* This program compiles, runs and outputs properly
* Example of a program with a function of
* arguments pnt2pnter
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
thoughtAsAFunction(iThink);
printf(":-)\n");
return 0;
}
void thoughtAsAFunction(char **iThink) {
int andy = 0;
for (; andy < 10;) {
char * pntThroughPnt = iThink[andy];
printf("%s", pntThroughPnt);
++andy;
}
andy = 0;
}
Or pass by reference, with an increment of the loop count variable:
/*
* This program compiles, runs, and outputs all of the character
* arrays.
*
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine, then I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
int andy = 0;
for (; andy < 10;) {
// pass by reference and increment.
thoughtAsAFunction(&iThink[andy]);
++andy;
}
printf(":-)\n");
andy = 0;
return 0;
}
void thoughtAsAFunction(char **iThink) {
char * pntThroughPnt = *iThink;
printf("%s", pntThroughPnt);
}
Keep in mind that this is the case if you declare the array of pointers (char *array[10];), and each pointer points to an array of characters.
I am programming in C. I am using also a library to create tasks which can communicate among them via messages. The content of these messages must be the pointer to the data you want to exchange.
In my case I want to send an array so I am sending a pointer to the array. In the receiving task I can then access the different elements by increasing the pointer, but, is there a way to know how long the array was?
Thank you in advance.
No, there is no way to do this as arrays decay to pointers when passed to functions, thus all information regarding size is lost.
You can include another parameter to specify the array length
void func(int len, int arr[]);
You can mark the end of the array with a special value (perhaps like argv does)
You can put your array into a structure and pass that (and suffer the performance penalties) or pass the a pointer to the structure
struct args {
int arr[100];
};
If you decide to go the first route, you can use a nice feature of C99, even if it doesn't actually enforce that arr has at least len elements:
void func(int len, int arr[len]);
No. So consider something slightly different.
struct arrayinfo {
struct element *array;
int count;
};
Then you can pass a pointer to your struct arrayinfo type and your receiving task will know how many elements are in your array.
An alternative technique is to make your array and array of pointers. Make your array one element bigger than necessary and set the last element to NULL.
No, you can't. The compiler doesn't know what the pointer is pointing to. You either need to pass the length value along with the array or you can trick it by allocating extra memory in order to store the length value before the start of the array.
No, that is not possible unless you also send the size of the array or set a guardian value in the end of the array.
I suggest that you do not send the array directly but use a intermediary struct, like the following:
struct intermediary {
int *the_array; /* the pointer to the array */
size_t size; /* the array size */
};
In the message you send the struct, and not the array itself.
Couldn't you use some kind of sentry value at the end of the buffers where the messages are stored. That should be such a value that you won't find it anywhere in the message. Depending on the type of these message its possible that there is such a value: typically a negative number if your messages consists of positive integers, a "INF" or "BIG_INT" number, etc. Then, you must process your message just up to the sentry value. Something like this:
#include <stdlib.h>
#include <string.h>
#define N 100
#define ENDTAG -999999
void foo( int *arr ){
int i = 0;
while( arr[i] != ENDTAG ){
//do whatever
i++;
}
}
int main( void ){
int *arr = (int *) malloc( sizeof(int) * N );
//fill the array, no matter how.
// ...
//set the sentry value
arr[N-1] = ENDTAG;
foo( arr );
free( arr );
return 0;
}
It may sound to much simple, but I actually used something like that more than once. You must though be absolutely sure that you'll take some restricted types of messages.
..
char arKey[1]; } Bucket;
The above is said to be flexible array,how?
Often the last member of a struct is given a size of 0 or 1 (despite 0 being against the standard pre-C99, it's allowed in some compilers as it has great value as a marker). As one would not normally create an array of size 0 or 1, this indicates to fellow coders that the field is used as the start of a variably sized array, extending from the final member into any available memory.
You may also find a member of the struct defining the exact length of the flexible array, just as you often find a member that contains the total size in bytes of the struct.
Links
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
Is using flexible array members in C bad practice?
http://msdn.microsoft.com/en-us/library/6zxfydcs(VS.71).aspx
http://blogs.msdn.com/b/oldnewthing/archive/2004/08/26/220873.aspx
Example
typedef struct {
size_t len;
char arr[];
} MyString;
size_t mystring_len(MyString const *ms) { return ms->len; }
MyString *mystring_new(char const *init)
{
size_t len = strlen(init);
MyString *rv = malloc(sizeof(MyString) + len + 1);
rv->len = len;
strncpy(rv->arr, init, len);
return rv;
}
Flexible arrays are supposed to have a length of 0 in C99. Using a size of 1 is C90 and is now deprecated.
Basically, such flexible arrays are created by invoking malloc with sizeof(Bucket) + array_length, where array_length is the desired size of your array. Then, dereferencing the arKey pointer (which must be the last member of your structure) will result in that extra memory being accessed, effectively implementing variable-sized objects.
See this page for more information:
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html