I am currently working on a personal AVR project and wrote a function for transmitting a double to my serial LCD screen using UART. For this, I convert a double into a char array and then transmit it char by char, serially.
What confuses me is what the length of the char buffer array has to be. The length of the array does not seem to correspond to the size of a double. Funnily enough, I can set the the length of the array to 0, and it will still work, like this:
void USART_Transmit_Double(double doubleNumber) {
char aNumberAsString[0];
dtostrf(doubleNumber, 3, 0, aNumberAsString);
USART_Transmit_String(aNumberAsString);
}
Here I am printing number 1234 in the main loop and it appears on my LCD just fine. If I change the precision to 1 however, the entire thing goes haywire.
I tested the same function on my Arduino and keep getting completely different results, on it each character seems to correspond to each element of the array, so if I wanted to print 1234.2, I would have to set the buffer length to 6.
So what's going on here?
You are running into undefined behavior. In particular, in this link, the phrase: Examples of undefined behavior are memory accesses outside of array bounds,... would likely apply to your described scenario. It may work a thousand times if the memory you are attempting to access (but do not own) does not happen to violate another variable's memory space. The first time it does, your program will crash.
The following statement, although legal, creates a useless variable, and is likely the reason you are seeing odd results:
char aNumberAsString[0];
Addressing your comment:
You may be confusing the index value necessary to create a buffer containing a single value, with the index value necessary to access that value once the variable is created. i.e.
char aNumberAsString[1] = 'A'; //creates an array of 1 char ([1])
will create a variable that can contain a single char value.
char value = aNumberAsString[0]; // accesses the only value in array ([0])
EXAMPLE:
See an example of how to use the dtostrf function here.
Note the size of the variables this example is using:
static float f_val = 123.6794;
static char outstr[15];
to support the following call:
dtostrf(f_val,7, 3, outstr);
Which produces the following output:
123.679
Related
I know that declaring a char[] variable in a while loop is scoped, having seen this post: Redeclaring variables in C.
Going through a tutorial on creating a simple web server in C, I'm finding that I have to manually clear memory assigned to responseData in the example below, otherwise the contents of index.html are just continuously appended to the response and the response contains duplicated contents from index.html:
while (1)
{
int clientSocket = accept(serverSocket, NULL, NULL);
char httpResponse[8000] = "HTTP/1.1 200 OK\r\n\n";
FILE *htmlData = fopen("index.html", "r");
char line[100];
char responseData[8000];
while(fgets(line, 100, htmlData) != 0)
{
strcat(responseData, line);
}
strcat(httpResponse, responseData);
send(clientSocket, httpResponse, sizeof(httpResponse), 0);
close(clientSocket);
}
Correct by:
while (1)
{
...
char responseData[8000];
memset(responseData, 0, strlen(responseData));
...
}
Coming from JavaScript, this was surprising. Why would I want to declare a variable and have access to the memory contents of a variable declared in a different scope with the same name? Why wouldn't C just reset that memory behind the scenes?
Also... Why is it that variables of the same name declared in different scopes get assigned the same memory addresses?
According to this question: Variable declared interchangebly has the same pattern of memory address that ISN'T the case. However, I'm finding that this is occurring pretty reliably.
Not completely correct. You don't need to clear the whole responseData array - clearing its first byte is just enough:
responseData[0] = 0;
As Gabriel Pellegrino notes in the comment, a more idiomatic expression is
responseData[0] = '\0';
It explicitly defines a character via its code point of zero value, while the former uses an int constant zero. In both cases the right-side argument has type int which is implicitly converted (truncated) to char type for assignment. (Paragraph fixed thx to the pmg's comment.)
You could know that from the strcat documentation: the function appends its second argument string to the first one. If you need the very first chunk to get stored into the buffer, you want to append it to an empty string, so you need to ensure the string in the buffer is empty. That is, it consists of the terminating NUL character only. memset-ting the whole array is an overkill, hence a waste of time.
Additionally, using a strlen on the array is asking for troubles. You can't know what the actual contents of the memory block allocated for the array is. If it was not used yet or was overwritten with some other data since your last use, it may contain no NUL character. Then strlen will run out of the array causing Undefined Behavior. And even if it returns successfuly, it will give you the string's length bigger than the size of the array. As a result memset will run out of the array, possibly overwriting some vital data!
Use sizeof whenever you memset an array!
memset(responseData, 0, sizeof(responseData));
EDIT
In the above I tried to explain how to fix the issue with your code, but I didn't answer your questions. Here they are:
Why do variables (...) in different scopes get assigned the same memory addresses?
In regard of execution each iteration of the while(1) { ... } loop indeed creates a new scope. However, each scope terminates before the new one is created, so the compiler reserves appropriate block of memory on the stack and the loop re-uses it in every iteration. That also simplifies a compiled code: every iteration is executed by exactly the same code, which simply jumps at the end to the beginning. All instructions within the loop that access local variables use exactly the same addressing (relative to the stack) in each iteration. So, each variable in the next iteration has precisely the same location in memory as in all previous iterations.
I'm finding that I have to manually clear memory
Yes, automatic variables, allocated on the stack, are not initialized in C by default. We always need to explicitly assign an initial value before we use it – otherwise the value is undefined and may be incorrect (for example, a floating-point variable can appear not-a-number, a character array may appear not terminated, an enum variable may have a value out of the enum's definition, a pointer variable may not point at a valid, accessible location, etc.).
otherwise the contents (...) are just continuously appended
This one was answered above.
Coming from JavaScript, this was surprising
Yes, JavaScript apparently creates new variables at the new scope, hence each time you get a brand new array – and it is empty. In C you just get the same area of a previously allocated memory for an automatic variable, and it's your responsibility to initialize it.
Additionally, consider two consecutive loops:
void test()
{
int i;
for (i=0; i<5; i++) {
char buf1[10];
sprintf(buf1, "%d", i);
}
for (i=0; i<1; i++) {
char buf2[10];
printf("%s\n", buf2);
}
}
The first one prints a single-digit, character representation of five numbers into the character array, overwriting it each time - hence the last value of buf1[] (as a string) is "4".
What output do you expect from the second loop? Generally speaking, we can't know what buf2[] will contain, and printf-ing it causes UB. However we may suppose the same set of variables (namely a single 10-items character array) from both disjoint scopes will get allocated the same way in the same part of a stack. If this is the case, we'll get a digit 4 as an output from a (formally uninitialized) array.
This result depends on the compiler construction and should be considered a coincidence. Do not rely on it as this is UB!
Why wouldn't C just reset that memory behind the scenes?
Because it's not told to. The language was created to compile to effective, compact code. It does as little 'behind the scenes' as possible. Among others things it does not do is not initializing automatic variables unless it's told to. Which means you need to add an explicit initializer to a local variable declaration or add an initializing instruction (e.g. an assignment) before the first use. (This does not apply to global, module-scope variables; those are initialized to zeros by default.)
In higher-level languages some or all variables are initialized on creation, but not in C. That's its feature and we must live with it – or just not use this language.
With this line:
char responseData[8000];
You are saying to your compiler: Hey big C, give me a 8000 bytes chunk and name it responseData.
In runtime, if you don't specify, no one will ever clean or give you a "brand-new" chunk of memory. That means that the 8000 bytes chunk you get in every single execution can hold all the possible permutations of bits in this 8000 bytes. Something extraordinary that can happens, is that you're getting in every execution the same memory region and thus, the same bits in this 8000 bytes your big C gave to you in the first time. So, if you don't clean, you have the impression that you're using the same variable, but you're not! You're just using the same (never cleaned) memory region.
I'd add that it's part of the programmer's responsibilities to clean, if you need to, the memory you're allocating, in dynamic or static way.
Why would I want to declare a variable and have access to the memory contents of a variable declared in a different scope with the same name? Why wouldn't C just reset that memory behind the scenes?
Objects with auto storage duration (i.e., block-scope variables) are not automatically initialized - their initial contents are indeterminate. Remember that C is a product of the early 1970s, and errs on the side of runtime speed over convenience. The C philosophy is that the programmer is in the best position to know whether something should be initialized to a known value or not, and is smart enough to do it themselves if needed.
While you're logically creating and destroying a new instance of responseData on each loop iteration, it turns out the same memory location is being reused each time through. We like to think that space is allocated for each block-scope object as we enter the block and released as we leave it, but in practice that's (usually) not the case - space for all block-scope objects within a function is allocated on function entry, and released on function exit1.
Different objects in different scopes may map to the same memory behind the scenes. Consider something like
void bletch( void )
{
if ( some_condition )
{
int foo = some_function();
printf( "%d\n", foo );
}
else
{
int bar = some_other_function();
printf( "%d\n", bar );
}
It's impossible for both foo and bar to exist at the same time, so there's no reason to allocate separate space for both - the compiler will (usually) allocate space for one int object at function entry, and that space gets used for either foo or bar depending on which branch is taken.
So, what happens with responseData is that space for one 8000-character array is allocated on function entry, and that same space gets used for each iteration of the loop. That's why you need to clear it out on each iteration, either with a memset call or with an initializer like
char responseData[8000] = {0};
As M.M points out in a comment, this isn't true for variable-length arrays (and potentially other variably modified types) - space for those is set aside as needed, although where that space is taken from isn't specified by the language definition. For all other types, though, the usual practice is to allocate all necessary space on function entry.
I'm in a sophomore C class and this project is about dealing with pointers and designing a memory dump function. So I've been able to struggle through the pointers and got a beginning and ending address to dump, even bitmasked it, and I wanted to initialize a char array with the beginning memory address. I initialize it with the same variable storing my masked beginning address but when I print the array, it contains a different memory address. Here's the function:
void memDump(void *base, int bytes)
{
unsigned char *begin;
begin = base;//beginning of range of memory
unsigned char *end;// ending range of memory
end = base + bytes;
int a, b;
long long int d=base;
d=d&0xFFFFF0; //trying to bitmask
long long int e=end;
e = e&0xFFFF0; //masked off the beginning and ending range
char c[16]={d}; //loop variables
printf("%x", c);
for (a=begin; a<=end; a+=16)
{
printf("\n%016X\n", d);
printf("%016X\n", a);
printf("%016X", e);
}
}
Sorry guys, i can't find something similar and this is my last resort. Thanks!
Update: Thanks for the insight everyone, reading some more about C and some articles on how to debug helped me out.
You cannot "initialize a char array" with some "memory address." A char array can only be initialized with characters.
Stackoverflow is not about doing your homework for you, so I will give you some advice, and then you can try implementing it. If you cannot put the advice into code, then you do not deserve to turn in a completed assignment.
First of all, once you have bitmasked your "d", you need to store it back into "begin", so that you have a pointer from which you can start reading bytes to dump.
This instruction:
printf( "%08p ", begin );
Will render the hexadecimal representation of your "begin" address in 8 characters, followed by a space. This is how you need to begin each row of your memory dump.
The instruction:
printf( "%02x ", *(begin++) );
gets the byte pointed by "begin", and renders the hexadecimal representation of that byte in two characters, followed by a space. It then increments "begin", to point to the next byte. You need to do this 8 or 16 times, depending on how wide you want your memory dump to be, then do a printf( "\n" ) to move to the next line.
Then you need to keep repeating the above until your "begin" has exceeded your "end". (So, you are looking at an outer loop, for each row, and an inner loop, for each byte within the row.)
I hope this helps.
As #Jean-FrançoisFabre observed,
char c[16]={d};
probably does not do what you think it does. That is, unless what you think it does is convert the long long int value stored in d to type char (producing an implementation-defined result drawn from a much smaller range than that of d itself), initializing the first element of array c with that value, and initializing the other fifteen with 0. I can't imagine what you would want to do with the result, but since you actually don't do anything with it, that's probably moot.
As I observed myself,
printf("%x", c);
also probably does not do what you think it does. Indeed, you cannot rely on it to do any particular thing, because its behavior is undefined. You are passing a pointer to the first element of c as the second argument, but a value of type unsigned int will be expected instead (based on the format). In any case, this neither "print[s] the array" nor tells you anything about what it contains.
I suspect that what you actually had in mind was to declare c as an array whose address -- not contents -- is that designated by base, truncated to a 16-byte-aligned address. You cannot do that, because you cannot specify the address of any variable you declare, but you can declare c as a pointer, like this:
unsigned char *c = d;
(Oh no, more pointers!) There's some implementation-dependency there, but it probably has the result I think you want. Or if you want to be really clever, you might do this:
unsigned char (*c16)[16] = d;
That declares c16 as a pointer to an array of 16 unsigned char. It's as close as you can get to declaring an array at an address specified by you. I suspect you'll find it easier to work with the other declaration, however.
If you want to print the contents of the memory to which such a pointer points (as a "memory dump" function seems wont to do) then you'll need to do a little more work. The standard library's formatted I/O functions do not provide directly for printing arrays (for good reasons that I'll not go into here), except C strings, and you do not appear to want to print the data as a C string. Do, however, consider this call, and how you might modify it for or adapt it to your purpose (assuming my above declaration for c):
printf("%02x", *c);
I have an array of bytes, if I just want X number of bytes in a specific location of that array, I am wondering if this is valid.
Also my code is crashing here, the following piece of code was provided to me.. but it crash on my system and don't know why.
rawDataPtr is my array of bytes, as you can guess the value that i am interested on starts on positon 4.
float TempFloat = COMMON_ConvertByteArrayToFloat(&rawDataPtr[3]);
Now the function.
union {
uint8_t tmpArray[4];
float tmpFloat;
}value;
float COMMON_ConvertByteArrayToFloat(uint8_t *data) {
value.tmpArray[0] = data[3];
value.tmpArray[1] = data[2];
value.tmpArray[2] = data[1];
value.tmpArray[3] = data[0];
return value.tmpFloat;
}
I have an array of bytes, if I just want X number of bytes in a specific location of that array, I am wondering if this is valid.
Supposing that "array" rawDataPtr has at least four elements, &rawDataPtr[3] is a valid pointer to the fourth. If the element type is different from uint8_t then you technically ought to cast to uint8_t * when you pass it to your function:
float TempFloat = COMMON_ConvertByteArrayToFloat((uint8_t *) &rawDataPtr[3]);
... but in practice that is unlikely to make any difference.
Your function is fine in itself. In particular,
there is no problem accessing data[0] ... data[3] as you do, provided that data is a valid pointer, and that referencing data[3] does not constitute an attempt to read outside the bounds of the object (in)to which data points. In the usage you present, that corresponds to rawDataPtr being an array of at least 7 bytes.
it is permissible to write to one element of a union and subsequently read from another, though there are some caveats. In particular, your code assumes that floats are four bytes in size; if they are longer on your system then your code has unspecified behavior.
Additional notes:
I assume it is intentional that you reverse the byte order from your array to form the value of your float. Whether that is appropriate is a function of your particular data.
If you are going to perform the bytes -> float conversion via a union, then it is advisable to use a union object that is local to the function. You presently appear to be using a file-scoped instance instead.
Your function is entirely capable of producing a trap representation in value.tmpFloat, and then attempting to read and return that value. If it does so then the resulting behavior is undefined.
Overall, if the function is crashing your program then it is because you are feeding it bad data. In that case, it is likely that either the caller's rawDataPtr is not a valid pointer (and note that it's name suggests that it is a pointer not an array), or it points to fewer than four bytes before the end of an object, or the bytes to which it points form a trap representation when converted.
Whats wrong with this C code lines
char *string()
{
char *text[20];
strcpy(text,"Hello world");
return text;
}
I was poor at pointers and I have seen this in some previous paper.
Can't able to solve.
It doesn't compile, since it treats an array of character pointers as a single array of characters.
The variable declaration line should be:
char text[200];
With that fix done, it's still broken for the reason you're probably interested in: it returns the address of a local variable (the text character array) which goes out of scope as the function returns, thus making the address invalid. There are two ways around that:
The easiest is to make the array static, since that makes it live for as long as the program runs.
You can also switch to dynamic (heap) memory by using malloc(), but that transfers ownership to the caller and requires a call to free() or memory will leak if this function gets called a lot.
Also, as a minor point, its name is in a reserved name space (user programs cannot define functions whose names begin with str). Also, a function taking no arguments should be declared as (void) in C, an empty pair of parentheses does not mean the same thing.
This code will not compile because you are trying to make an array of pointers.
In simple words if you want to handle string using pointer you can do using following:
char *str="HELLO WORLD";
And if you want to handle string using char array you have to remove value at address operator(*).
here it is:
char text[20];
then you can perform your function.
Still there is error as the Scope of the text is only valid inside the function so if you want to pass address and retain the value make it static
static char text[20];
return text;
I have a question about how is the correct way of manipulate the initialization of c strings
For example the next code, isn't always correct.
char *something;
something = "zzzzzzzzzzzzzzzzzz";
i test a little incrementing the number of zetas and effectively the program crash in like about two lines, so what is the real size limit in this char array? how can i be sure that it is not going to crash, is this limit implementation dependent? Is the following code the correct approach that i always must use?
char something[FIXEDSIZE];
strcpy(something, "zzzzzzzzzzzzzzzzzzz");
As you say, manipulating this string leads to undefined behaviour:
char *something;
something = "zzzzzzzzzzzzzzzzzz";
If you are curious as to why, see "C String literals: Where do they go?".
If you plan to manipulate your string at all, (i.e. if you want it to be mutable) you should use this:
char something[] = "skjdghskfjhgfsj";
Otherwise, simply declare your char * as a const char * to indicate that it points to a constant.
In the second example, the compiler will be smart enough to declare this as an array on the stack of the exact size to hold the string. Thus, the size of this is limited by your stack.
Of course, you will likely want to specify the size anyway, since it is usually useful to know when manipulating the string.
The second is always correct.
The first is correct only if you never change the string, since you've assigned a pointer to fixed data.
The first example is only incorrect in that char *something should really be const char *something. Otherwise, this:
const char *something = "fooooooooooooooooooooooobar";
...should work, and should not crash.
char something[FIXEDSIZE];
...this one, however, can typically crash with a stack overflow if you, well, overflow the stack, which depends on how big that stack is, how big that array is, where this gets called, etc.
first should never crash. second will crash as soon as the number of 'z' + 1 go over the available space on the stack page, or if you try to return from the function.