I would like to know how the result of the memcpy() with respect to the memory allocation.
#include<stdio.h>
#include<string.h>
typedef struct {
char myname[7] ;
} transrules;
trans typedef struct {
char ip ;
int udp;
transrules rules[256];
} __attribute__ ((__packed__)) myudp;
myudp __attribute__ ((__packed__)) udpdata ;
char arr[400] ;
int main() {
memset (&udpdata , 0 ,sizeof(udpdata));
udpdata.ip = 'a' ;
udpdata.udp = 13 ;
udpdata.rules[0].myname = "lalla\0" ;
memcpy (&arr , &udpdata, sizeof(udpdata));
printf("%c",arr[0]);
return 0;
}
With respect to the code , how do we print out the character array in the structure transrules?
PS : Yes this code throws an error, sheesh char's !
As the array defined is of type char why does arr [1] still accept an integer value with memcpy() ?
memcpy does not allocate any memory. In your memcpy call, the memory for the destination arr was allocated when the variable arr was defined (char arr[400]).
There's a problem there, which is that you haven't allocated enough room. You copy sizeof(updata) bytes into arr, which is probably 1+4+7*256=1797 (this may vary depending on sizeof(int) and on whether __packed__ actually leaves out all unused bytes on your platform). If you really need arr (you probably don't), make it at least sizeof(updata) large. Defining it with char arr[sizeof(updata)] is fine.
If the layout of the structure is defined by some external format, you should use a fixed-size type instead of int (which is 2 or 4 bytes depending on the platform, and could be other sizes but you're unlikely to encounter them).
If the layout of the structure is defined by some external binary format and you want to print out the 1797 bytes in this format, use fwrite.
fwrite(updata, sizeof(updata), 1, stdout);
If you want to have a human representation of the data, use printf with appropriate format specifications.
printf("ip='%c' udp=%d\n", updata.ip, updata.ip);
for (i = 0; i < sizeof(updata.rules)/sizeof(updata.rules[0]); i++) {
puts(updata.rules[i].myname);
}
Despite the name, char is in fact the type of bytes. There is no separate type for characters in C. A character constant like 'a' is in fact an integer value (97 on almost all systems, as per ASCII). It's things like writing it with putchar or printf("%c", …) that make the byte interpreted as a character.
If your compiler is not signaling an error when you mix up a pointer (such as char*) with an integer, on the other hand, turn up the warning level. With Gcc, use at least gcc -O -Wall.
After actually compiling your code, I see the main error (you should have copy-pasted the error message from the compiler in your question):
udpdata.rules[0].myname = "lalla\0" ;
udpdata.rules[0].myname is an array of bytes. You can't assign to an array in C. You need to copy the elements one by one. Since this is an array of char, and you want to copy a string into it, you can use strcpy to copy all the bytes of the string. For a bunch of bytes in general, you would use memcpy.
strcpy(udpdata.rules[0].myname, "lalla");
(Note that "lalla\0" is equivalent to "lalla", all string literals are zero-terminated in C.¹) Since strcpy does not perform any size verification, you must make sure that the string (including its final null character) fits in the memory that you've allocated for the targets. You can use other functions such as strncat or strlcpy if you want to specify a maximum size.
¹ There's one exception (and only this exception) where "lalla" won't be zero-terminated: when initializing an array of 5 bytes, e.g. char bytes[5] = "lalla". If the array size is at least 6 or unspecified, there will be a terminating zero byte.
// this is really bad
udpdata.rules[0].myname = "lalla\0" ;
// do this instead. You want the literal string in your field.
memcpy(udpdata.rules[0].myname, "lalla\0", 6);
....
// This is wrong. arr is already a pointer.
memcpy (&arr , &udpdata, sizeof(udpdata));
// do this instead
mempcy (arr, &udpdata, sizeof(udpdate));
Concerning printing, I don't know how big ints are on your machine but if they are 4 bytes then
printf("%.7s", &arr[1+4]);
I'm not sure why you want to convert everything to a char array if you wanted to print out the content. Just use the struct and a for loop. Anyway I think you may want to read up on C arrays.
With respect to the code , how do we print out the character array in the structure transrules ?
/* incorrect -> udpdata.rules[0].myname = "lalla\0" ; */
strcpy(udpdata.rules[0].myname,"lalla") ;
printf("%s\n",udpdata.rules[0].myname);
As the array defined is of type char why does arr [1] still accept an integer value with memcpy ?
memcpy doesn't know or care about what the underlying datatypes might be where it is copying to. It takes void pointers and copies the value in one or more byte to one or more other bytes:
void * memcpy ( void * destination, const void * source, size_t num );
Related
I've read several answers for this question but can't fully understand. How does the compiler know the end of an array. If we suppose that an array of 4 int is located in memory just before an another int, can we by mistake write array[4] and it will give us this 5th int? I suppose no so how the compilers knows there are only 4 elements?
If you're lucky, the compiler might spot that you're writing beyond the end of the array, and flag it as a warning, but it's not actually a compile-time error.
If you have this code:
static int a[4];
static int b;
// ...
a[4] = 42;
You'd actually discover that b now has the value 42, unless the compiler decided to put it somewhere else.
Yes, it's that easy to overrun an array in C. There are no guard rails.
In fact, this behaviour is explicitly relied upon in some places, although it's not recommended any more. You might declare a struct as follows:
struct comms_block {
enum comms_block_type block_type;
size_t len;
uint8_t variable_data[1];
};
And then, when you wanted to create a comms block of type t, with variable data length len, you would use a function like this:
struct comms_block *new_comms_block(enum_comms_block_type t, size_t len)
{
struct comms_block *b = malloc(sizeof(*b) + len - 1);
b->block_type = t;
b->len = len;
return b;
}
The function returns a struct comms_block with len bytes of space from variable_data[0] onwards.
You can safely index variable_data[] using any value up to (len - 1) despite that it's only declared as a single-byte array in the struct definition.
In the context where the array is defined, the bounds are specified and the compiler knows the length. A sizeof is possible.
In the contexts where the array is passed as an argument, only the starting address is given and the compiler does not know the length at all.
This is a terrible source of weird bugs by buffer overflow.
In some cases, static analysis could let a compiler warn about obvious buffer overflows, but not always.
Compilers read and interpret the source code (where the array variable is dimensioned to have 4 elements.) Modern compilers (and add-ons) can analyse the source code (as the programmer should) and, through that evaluation, determine if "rules are being broken"...
char a[4]; // set aside 4 bytes (uninitialised)
char a[] = { 'a', 'b', 'c', 'd' }; // set aside 4 bytes (initialised)
// Above is NOT a string!
char a[] = "abc"; // 3 + 1 bytes initialised
// Above IS a string (null terminated array of chars.
The compiler "sees" this and "knows" how big 'a[]' is.
**
char a[4]={'w', 'x', 'y', 'z'};//here index of w is 0 and the index
of last element in 3 ... // so you may have question like what is
stored in a[4] ... It's nothing but '\0' it means null character..
// compiler will understand that it is the end of character array..
**
Hope you got what you asked
Related: flexible array member in a nested struct
I am trying to parse some data into a struct. The data contains information organized as follows:
struct unit {
struct unit_A {
// 28 bytes each
// dependency r6scA 1
char dr6scA1_tagclass[4];
uint32_t dr6scA1_tagnamepointer;
uint32_t dr6scA1_tagnamestringlength;
uint32_t dr6scA1_tagid;
// 12 bytes of 0x00
}A;
// A strings
struct unit_B {
// 48 bytes each
// dependency r6scB 1
char dr6scB1_tagclass[4];
uint32_t dr6scB1_tagnamepointer;
uint32_t dr6scB1_tagnamestringlength;
uint32_t dr6scB1_tagid;
// 32 bytes of 0x00
}B;
// B strings
// unit strings
}unit_container;
You can ignore the weird nomenclature.
My line comments // A strings, // B strings and // unit strings each contain null-terminated C strings, the numbers of which coincides with however many unit_A, unit_B, and unit struct entries there are in the data. So like if there are 5 entries of A in unit_container, then there would be 5 C strings in the location where it says // A strings.
Since I cannot use flexible array members at these locations, how should I interpret what are essentially an unknown number of variable-length C strings at these locations in the data?
For example, the data at these locations could be:
"The first entry is here.\0Second entry\0Another!\0Fourth.\0This 5th entry is the bestest entry evah by any reasonable standards.\0"
...which I expect I should interpret as:
char unit_A_strings[]
...but this is not possible. What are my options?
Thank you for your consideration.
EDIT:
I think the most attractive option so far is:
char** unit_A_strings; to point to an array of char strings.
If I do:
char unit_A_strings[1]; to define a char array of fixed size of 1 char, then I must abandon sizeof(unit) and such, or hassle with memory allocation sizes, even though it is most accurate to the kind of data present. The same situation occurs if I do char * unit_A_strings[1];.
Another question: What would be the difference between using char *unit_A_strings; and char** unit_A_strings;?
Conclusion:
The main problem is that structs are intended for fixed-size information and what I am needing is a variable-sized information memory region. So I can't legitimately store the data into the struct -- at least not as the struct. This means that any other interpretation would be alright, and it seems to me that char** is the best available option for this struct situation.
I think it can using the char** instead (Or you can write some structure to wrapper it).
for example, you can write a help function to decode you stream.
char** decodeMyStream(uint_8* stream, unsigned int* numberOfCString)
{
*numberOfCString = decodeNumberOfCString(stream);
char** cstrings = malloc((*numberOfCString) * sizeof(char*));
unsigned int start = 0;
for (unsigned int i = 0; i < *numberOfCString; ++i)
{
usigned int len = calculateIthStringLength(stream, start)
cstrings[i] = malloc((len) * sizeof(char));
memcpy(cstrings[i], stream + start, len);
start += len
}
return cstrings;
}
it just no thinking example code, you can think out more better algorithms.
I think the closest you're going to get is by providing an array of strings:
char *AStrings[] = { "The first entry is here.",
"Second entry",
"Another!",
"Fourth.",
"This 5th entry is the bestest entry evah by any reasonable standards.",
NULL
};
Note two things:
AStrings is an array of pointers-to-strings - it will be 6 (see 2. below) consecutive pointers that point to the actual strings, NOT the 'compound' string you used in your example.
I ended AStrings with a NULL pointer, to resolve the "when do I finish?" question.
So you can "fall off the end" of A and start looking at locations as pointers - but be careful! The compiler may put in all sorts of padding between one variable and the next, mucking up any assumptions about where they are relative to each other in memory - including reordering them!
Edit
Oh! I just had a thought. Another data representation that may help is essentially what you did. I've 'prettied' it up a bit:
char AString[] = "The first entry is here.\0"
"Second entry\0"
"Another!\0"
"Fourth.\0"
"This 5th entry is the bestest entry evah by any reasonable standards.\0";
The C compiler will automatically concatenate two 'adjacent' strings as though they were one string - with no NUL character between them. I put them in specifically above.
The C compiler will automatically put a '\0' at the end of any string - at the semicolon (;) in the above example. That means that the string actually ends with two NUL characters, not one.
You can use that fact to keep track of where you are while parsing the string 'array' - assuming that every desired value has a (sub)string of more than zero length! As soon as you encounter a zero-length (sub)string, you know you've reached the end of the string 'array'.
I call these kind of strings ASCIIZZ strings (ASCIIZ strings with a second NUL at the end of all of them).
Hi i am having 2 questions here
How do i store a hex value in a buffer, say for example 0x0a and 0x1F;
char buffer[2] = "0x0a 0x1F";
But this is not right method, It is giving size 10 instead of 2. Can any one suggest how can i proceed.
I have seen the array like this
char buffer[] = " static array";
In the structure also,
struct Point {
char x[];
char y[];
};
what does it mean? how much size it will take for compilation
For the first, assuming you really want a two-byte array rather than a three-byte string (including NULL terminator), you can use:
char buffer[] = {0x0a, 0x1f};
For the second, the easiest way to find out is to simply check:
sizeof(buffer)
or:
sizeof(struct Point)
although I'm pretty certain your structure definition will fail because char x[] is not a complete type. Current versions of the standard allow flexible array sizes at the end of structures but not the way you have it there.
Likely sizes of the two (once you declare struct Point with char x[5]) will be 14 (number of characters in " static array" including the NULL terminator) and 5 (the size of x itself (flexible array members tend not to take up space, they're more for allowing arbitrary extra space if the memory block is obtained by malloc, for example).
I'm trying to learn C and as a start, i set off writing a strcpy for my own practice. As we know, the original strcpy easily allows for security problems so I gave myself the task to write a "safe" strcpy.
The path I've chosen is to check wether the source string (character array) actually fits in the destination memory. As I've understood it, a string in C is nothing more than a pointer to a character array, 0x00 terminated.
So my challenge is how to find how much memory the compiler actually reserved for the destination string?
I tried:
sizeof(dest)
but that doesn't work, since it will return (as I later found out) the size of dest which is actually a pointer and on my 64 bit machine, will always return 8.
I also tried:
strlen(dest)
but that doesn't work either because it will just return the length until the first 0x0 is encountered, which doesn't necessarily reflect the actual memory reserved.
So this all sums up to the following question: How to find our how much memory the compiler reserved for my destination "string"???
Example:
char s[80] = "";
int i = someFunction(s); // should return 80
What is "someFunction"?
Thanks in advance!
Once you pass a char pointer to the function you are writing, you will loose knowledge for how much memory is allocated to s. You will need to pass this size as argument to the function.
You can use sizeof to check at compile time:
char s[80] = "";
int i = sizeof s ; // should return 80
Note that this fails if s is a pointer:
char *s = "";
int j = sizeof s; /* probably 4 or 8. */
Arrays are not pointers. To keep track of the size allocated for a pointer, the program simply must keep track of it. Also, you cannot pass an array to a function. When you use an array as an argument to a function, the compiler converts that to a pointer to the first element, so if you want the size to be avaliable to the called function, it must be passed as a parameter. For example:
char s[ SIZ ] = "";
foo( s, sizeof s );
So this all sums up to the following question: How to find our how much memory the compiler reserved for my destination "string"???
There is no portable way to find out how much memory is allocated. You have to keep track of it yourself.
The implementation must keep track of how much memory was malloced to a pointer, and it may make something available for you to find out. For example, glibc's malloc.h exposes
size_t malloc_usable_size (void *__ptr)
that gives you access to roughly that information, however, it doesn't tell you how much you requested, but how much is usable. Of course, that only works with pointers you obtained from malloc (and friends). For an array, you can only use sizeof where the array itself is in scope.
char s[80] = "";
int i = someFunction(s); // should return 80
In an expression s is a pointer to the first element of the array s. You cannot deduce the size of an array object with the only information of the value of a pointer to its first element. The only thing you can do is to store the information of the size of the array after you declare the array (here sizeof s) and then pass this information to the functions that need it.
There's no portable way to do it. However, the implementation certainly needs to know this information internally. Unix-based OSes, like Linux and OS X, provide functions for this task:
// OS X
#include <malloc/malloc.h>
size_t allocated = malloc_size(somePtr);
// Linux
#include <malloc.h>
size_t allocated = malloc_usable_size(somePtr);
// Maybe Windows...
size_t allocated = _msize(somePtr);
A way to tag the member returned by malloc is to always malloc an extra sizeof(size_t) bytes. Add that to the address malloc returns, and you have a storage space for storing the actual length. Store the malloced size - the sizeof (size_t) there, and you have the basis for your new set of functions.
When you pass two of these sorts of pointers into your new-special strcpy, you can subtract sizeof(size_t) off the pointers, and access the sizes directly. That lets you decide if the memory can be copied safely.
If you are doing strcat, then the two sizes, along with calculating the strlens means you can do the same sort of check to see if the results of the strcat will overflow the memory.
It's doable.
It's probably more trouble than it's worth.
Consider what happens if you pass in a character pointer that was not mallocated.
The assumption is that the size is before the pointer. That assumption is false.
Attempting to access the size in that case is undefined behavior. If you are lucky, you may get a signal.
One other implication of that sort of implementation is that when you go to free the memory, you have to pass in exactly-the-pointer-that-malloc-returned. If you don't get that right, heap corruption is possible.
Long story short...
Don't do it that way.
For situations where you are using character buffers in your program, you can do some smoke and mirrors to get the effect that you want. Something like this.
char input[] = "test";
char output[3];
if (sizeof(output) < sizeof(input))
{
memcpy(output,input,sizeof(input) + 1);
}
else
{
printf("Overflow detected value <%s>\n",input);
}
One can improve the error message by wraping the code in a macro.
#define STRCPYX(output,input) \
if (sizeof(output) < sizeof(input)) \
{ \
memcpy(output,input,sizeof(input) + 1); \
} \
else \
{ \
printf("STRCPYX would overflow %s with value <%s> from %s\n", \
#output, input, #input); \
} \
char input[] = "test";
char output[3];
STRCPYX(output,input);
While this does give you what you want, the same sort of risks apply.
char *input = "testing 123 testing";
char output[9];
STRCPYX(output,input);
the size of input is 8, and output is 9, the value of output ends up as "Testing "
C was not designed to protect the programmer from doing things incorrectly.
It is kind of like you are attempting to paddle upriver :)
It is a good exercise to think about.
Although arrays and pointers can appear to be interchangeable, they differ in one important aspect; an array has size. However because an array when passed to a function "degrades" to a pointer, the size information is lost.
The point is that at some point you know the size of the object - because you allocated it or declared it to be a certain size. The C language makes it your responsibility to retain and disseminate that information as necessary. So after your example:
char s[80] = ""; // sizeof(s) here is 80, because an array has size
int i = someFunction(s, sizeof(s)) ; // You have to tell the function how big the array is.
There is no "magic" method of determining the size of the array within someFunction(), because that information is discarded (for reasons of performance and efficiency - C is relatively low level in this respect, and does not add code or data that is not explicit); if the information is needed, you must explicitly pass it.
One way in which you can pass a string and retain size information, and even pass the string by copy rather than by reference is to wrap the string in a struct thus:
typedef struct
{
char s[80] ;
} charArray_t ;
then
charArray_t s ;
int i = someFunction( &s ) ;
with a definition of someFunction() like:
int someFunction( charArray_t* s )
{
return sizeof( s->s ) ;
}
You don't really gain much by doing that however - just avoid the additional parameter; in fact you loose some flexibility because someFunction() now only takes a fixed array length defined by charrArray_t, rather than any array. Sometimes such restrictions are useful. On feature of this approach is that you can pass by copy this:
int i = someFunction( s ) ;
then
int someFunction( charArray_t s )
{
return sizeof( s.s ) ;
}
since structures unlike arrays can be passed this way. You can equally return by copy as well. It can be somewhat inefficient however. Sometimes the convenience and safety outweigh the inefficiency however.
I have a structure that has an array of pointers. I would like to insert into the array digits in string format, i.e. "1", "2", etc..
However, is there any difference in using either sprintf or strncpy?
Any big mistakes with my code? I know I have to call free, I will do that in another part of my code.
Many thanks for any advice!
struct port_t
{
char *collect_digits[100];
}ports[20];
/** store all the string digits in the array for the port number specified */
static void g_store_digit(char *digit, unsigned int port)
{
static int marker = 0;
/* allocate memory */
ports[port].collect_digits[marker] = (char*) malloc(sizeof(digit)); /* sizeof includes 0 terminator */
// sprintf(ports[port].collect_digits[marker++], "%s", digit);
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
}
Yes, your code has a few issues.
In C, don't cast the return value of malloc(). It's not needed, and can hide errors.
You're allocating space based on the size of a pointer, not the size of what you want to store.
The same for the copying.
It is unclear what the static marker does, and if the logic around it really is correct. Is port the slot that is going to be changed, or is it controlled by a static variable?
Do you want to store only single digits per slot in the array, or multiple-digit numbers?
Here's how that function could look, given the declaration:
/* Initialize the given port position to hold the given number, as a decimal string. */
static void g_store_digit(struct port_t *ports, unsigned int port, unsigned int number)
{
char tmp[32];
snprintf(tmp, sizeof tmp, "%u", number);
ports[port].collect_digits = strdup(tmp);
}
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
This is incorrect.
You have allocated onto collect_digits a certain amount of memory.
You copy char *digits into that memory.
The length you should copy is strlen(digits). What you're actually copying is sizeof(ports[port].collect_digits[marker]), which will give you the length of a single char *.
You cannot use sizeof() to find the length of allocated memory. Furthermore, unless you know a priori that digits is the same length as the memory you've allocated, even if sizeof() did tell you the length of allocated memory, you would be copying the wrong number of bytes (too many; you only need to copy the length of digits).
Also, even if the two lengths are always the same, obtaining the length is this way is not expressive; it misleads the reader.
Note also that strncpy() will pad with trailing NULLs if the specified copy length is greater than the length of the source string. As such, if digits is the length of the memory allocated, you will have a non-terminated string.
The sprintf() line is functionally correct, but for what you're doing, strcpy() (as opposed to strncpy()) is, from what I can see and know of the code, the correct choice.
I have to say, I don't know what you're trying to do, but the code feels very awkward.
The first thing: why have an array of pointers? Do you expect multiple strings for a port object? You probably only need a plain array or a pointer (since you are malloc-ing later on).
struct port_t
{
char *collect_digits;
}ports[20];
You need to pass the address of the string, otherwise, the malloc acts on a local copy and you never get back what you paid for.
static void g_store_digit(char **digit, unsigned int port);
Finally, the sizeof applies in a pointer context and doesn't give you the correct size.
Instead of using malloc() and strncpy(), just use strdup() - it allocates the buffer bin enough to hold the content and copies the content to the new string, all in one shot.
So you don't need g_store_digit() at all - just use strdup(), and maintain marker on the caller's level.
Another problem with the original code: The statement
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
references marker and marker++ in the same expression. The order of evaluation for the ++ is undefined in this case -- the second reference to marker may be evaluated either before or after the increment is performed.