I need an array of strings. The length of a string is known at compile-time and it is crucial that each string takes up this much space. The number of strings on the other hand is only known at runtime. What is the syntax for this?
char* data[STRLENGTH] is incorrect syntax. char** data mostly works but then sizeof(data[0]) is wrong -- it should be equal to STRLENGTH.
#Daniel is correct, but this code can confuse people who read it - it's not something you usually do. To make it more understandable, I suggest you do it in two steps:
typedef char fixed_string[STRLENGTH];
fixed_string *data;
char (*data)[LEN]; // where LEN is known at compile time
...
data = malloc(sizeof *data * rows); // where rows is determined at run time
...
strcpy(data[i], some_name);
...
printf("name = %s\n", data[i]);
...
free(data);
Note that data is a pointer type, not an array type (data is a pointer to a LEN-element array of char). The malloc call will dynamically allocate enough memory to hold rows arrays of length LEN. Each data[i] will be type char [LEN].
char* data[STRLENGTH]
declares an array of STRLENTGH pointers to char. To declare a pointer to array of STRLENGTH chars, use
char (*data)[STRLENGTH]
Related
There is a struct like this:
struct sdshdr {
int len;
int free;
char buf[];
};
And the result of printf ("%d\n", sizeof(struct sdshdr));is 8. If I change char buf[] to char *, the result would be 16. Why is char buf[] taking no space here(sizeof(int) is 4)? When shoud I choose char buf[] over char *buf?
The construct with the empty brackets [] is allowed as the last element of the struct. It lets you allocate additional space beyond sizeof(sdshdr) for the elements of the array, letting you embed the array data with the array itself.
Pointers, on the other hand, store the data in a separately managed segment of memory, and require an additional call to free at the end. Unlike the [] way, pointers let you have more than one variable-length array inside the same struct, and the element can be placed anywhere in the struct, not only at the end of the struct.
Taking "char[]" more generally:
char[] will actually allocate a number of characters inside the struct. (A struct with char x[17] will grow by 17 bytes and so on.) A char* will just hold a pointer.
An actual char x[] (with no size specified - and I think the same goes for size 0) at the end of the struct is a special case called a "flexible array member" and is discussed in the linked question and in the other answer.
Remember also that sizeof needs to be determined at compile time. Since char buf[] is a flexible array member it's size cannot be known at compile time, therefore will be omitted from the calculation of sizeof.
char * is a pointer to a char variable, and it's size is known so is included (however that is the size of the pointer not the array it points to).
In this code, the "array" is an array of pointers to chars? Or something else?
struct tmep{
char (*array) [SIZE];
}
Thanks in advance :)
It's a pointer to an array of SIZE chars.
Declaration mimics use, so you evaluate the parenthesis first, (*array) gives you a char[SIZE].
To allocate, the stable version is as usual
array = malloc(num_elements * sizeof *array);
to specify the size of each object (char[SIZE] here) in the block by taking the sizeof the dereferenced pointer. You don't need to change that allocation if the type changes e.g. to int (*)[SIZE].
If you want to specify the type,
array = malloc(num_elements * sizeof(char (*)[SIZE]));
This allocates - if malloc succeeds - a block large enough for num_elements arrays of SIZE chars, each of these arrays is accessed with
array[i]
and the chars in the arrays in the block with
array[i][j]
I want to create an array of strings. The problem is that I want to be able to access the length of each string statically. I tried this:
char *a[] = {"foo", "foobar"};
The array works fine except that I want to know the length of each element statically.
I can't use sizeof(a[0]) because it returns the size of the char * pointer. What I want is the length of the size of the string (4 for a[0], 7 for a[1]).
Is there any way to do this?
In short, no, not at compile-time (at least not for an arbitrary number of strings). There are various run-time initialization-like things you can do, as others have pointed out. And there are solutions for a fixed number of strings, as others have pointed out.
The type of a[0] must be the same as that of a[1] (obviously). So sizeof() must evaluate to the same for all values of a[i].
Depending on your definition of "string", a is not an array of strings: it is an array of pointers (I define "string" as array of N characters including a null terminator).
If you want an array of lengths and strings (each capable of holding 999 characters and the null terminator), you may do something like
struct lenstring { size_t len; char data[1000]; };
struct lenstring a[] = {
{ sizeof "foo" - 1, "foo" },
{ sizeof "foobar" - 1, "foobar" },
};
Example with simplifying macro running at ideone
The only safe way to know the length of strings statically is to declare them all individually.
char foo[] = "foo";
char foobar[] = "foobar";
char *a[] = {foo, foobar};
You might be able to use a macro to eliminate some of the drudgery, depending on the strings' contents. sizeof(a[0]) will still be sizeof(char*), though.
You can't statically initialize a data structure with the result of strlen(), you could loop over your strings and store the string length in an initialization function.
You can't. sizeof doesn't return the length of the string, but the size of the array, which in your second case is much larger than the length of the string. You need to use strlen or, perhaps, a more featured string type:
struct {
size_t len;
char data[];
} string;
But it'd be a bit more complicated to make an array of them in that case.
if you use char*a[] = {"foo", ...} style of decleration, then you can use strlen(a[0]), strlen(a[1]) etc to find the length of each string.
Maybe you could start with something like this:
size1 = abs(a[0] - a[1]);
That will give you the difference between the beginning address of the first string and the beginning address of the second string. Therefore the size of the first string.
Then you could use some loop and array to get all the sizes.
It is not statically but maybe you could try it.
Is this possible?
size_t calculate(char *s)
{
// I would like to return 64
}
int main()
{
char s[64];
printf("%d", calculate(s));
return 0;
}
I want to write a function which calculates the size of the char array declared in main().
Your function calculate(), given just the pointer argument s, cannot calculate how big the array is. The size of the array is not encoded in the pointer, or accessible from the pointer. If it is designed to take a null-terminated string as an argument, it can determine how long that string is; that's what strlen() does, of course. But if it wants to know how much information it can safely copy into the array, it has to be told how big the array is, or make an assumption that there is enough space.
As others have pointed out, the sizeof() operator can be used in the function where the array definition is visible to get the size of the array. But in a function that cannot see the definition of the array you cannot usefully apply the sizeof() operator. If the array was a global variable whose definition (not declaration) was in scope (visible) where calculate() was written - and not, therefore, the parameter to the function - then calculate() could indicate the size.
This is why many, many C functions take a pointer and a length. The absence of the information is why C is somewhat prone to people misusing it and producing 'buffer overflow' bugs, where the code tries to fit a gallon of information into a pint pot.
On statically declared char[] you can use operator sizeof, which will return 64 in this case.
printf("%d", sizeof(s));
On dynamically declared char*, it is not possible to get the size of the allocated memory.
Dynamic arrays are obtained through malloc and friends. All the others are statically declared, and you can use sizeof on them, as long as you use it in the same scope as the array was declared (same function, in your case, for example).
Yes, it's possible if s has a specific character in the end of it's array. For example you could have s[63] = 125 and by knowing that every other character from 0 to 62 won't be 125, you can do a for loop until you find 125 and return the size of the array.
Otherwise, it's not possible, as s in the function parameter is just a pointer to your array, so sizeof(s) inside calculate will only return your machines pointer size and not 64 as someone could expected.
Unfortunately, you cannot determine from a pointer value alone how many elements are in the corresponding array. You either need some sort of sentinel value in the array (like the 0 terminator used for strings), or you need to keep track of it separately.
What you can do is get the number of bytes or elements in an array using the sizeof operator:
char arr[64];
size_t size = sizeof arr; // # of bytes in arr
size_t count = sizeof arr / sizeof *arr; // # of elements in arr
However, this only works if arr is an array type; if you tried to do this in your function
size_t calculate(char *s)
{
return sizeof s;
}
it would return the size in bytes of the pointer value, not of the corresponding array object.
No. char *x or char x[] just creates a pointer to a memory location. A pointer doesn't hold any information about the size of the memory region.
However, char *x = "Hello" occupies 6 bytes (including the terminating null), and strlen(x) would return 5. This relies on the null char at the end of the string, strlen still knows nothing about the underlying buffer. So strlen("Hello\000There") would still be 5.
This is usually done with a macro in C, like:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
Whether it's a good idea is a totally different question.
I'm having some issues with storing an address of a specific value in an array of strings to a pointer and printing it out. Please excuse the bad variable names, they are just for the example.
char **code; // code is an array of 100 strings of length 8 characters
code = malloc (100*sizeof(*code));
for (i=0; i<100; i++) {
code[i]=malloc(8*sizeof(**code));
}
char **r; // r is an array of 16 strings of 32 characters
r = malloc (16*sizeof(*r));
for (i = 0; i < 16; i++)
r[i] = malloc(32*sizeof(**r));
char *a; // a is a pointer to a string
a = (char *) &r[13]; // point a to value at r[13]
*a = (char *)&code[100]; // trying to assign the value of r[13] to the address of code[100]
printf("Code 100 Add: %p a Val: %i\n", &code[100], *sp); // trying to check values.
I'm trying to assign the value of a (which points to r[13], so assign value of r[13]) to the value of the Address of the string at code[100]. Is even a string of 32 characters the best way to do this?
Appreciate any help,
Gareth
a = (char *) &r[13]; // point a to value at r[13]
Turn on your compiler warnings, and pay attention to what the compiler tell you when you remove this cast. You shouldn't need any casts in this code.
The type of r is char** and so the type of r[13] is char*, and the type of &r[13] is char**, which you're assigning to a char*.
P.s., next time please also include the actual error you receive vs what you expected.
To assign a string, use strncpy. Don't copy the pointer value directly because you will free it twice later this way (among other problems).
&r[13] is not a pointer to char.
You just need to
r[13] = code[100]
I do agree with Frederik that you should be careful when free()-ing the allocated memory since you now have two pointers pointing at the same memory block. If you prefer to follows his advice, try the following:
strncpy(r[13], code[100], 8)
Rather than assigning a pointer to a memory address, you're going to want to copy the data at that memory address using strcpy.
With definition of char *a; the *a on the left-hand side of an assignment becomes an lvalue of type char. You can assign pointer values there as integers, as in square peg into a round hole, though it does not make much sense. To copy strings use str[nl]cpy(3).
I hate to ask a question during someone else's question... but shouldn't the char array setup/malloc calls be something more like this? Isn't he allocating too much with sizeof(**code)? And then... if it's for 8 characters... won't we want 9 to make room for '\0'?
char **code; // code is an array of 100 strings of length 8 characters
code = (char**) malloc (100*sizeof(char*));
for (i=0; i<100; i++) {
code[i] = (char*)malloc(9*sizeof(char));
}