Storing of string literals in consecutive memory locations - c++

#include <stdio.h>
#include <string.h>
int main() {
char *s[] = {"cricket","tennis","football"};
printf(" String are: \n\n");
printf(" %s \n", *(s));
printf(" %s \n", *(s+1));
printf(" %s \n", *(s+2));
printf(" \n\n");
printf(" Starting locations of the string are: \n\n");
printf(" %d\n",*(s));
printf(" %d\n",*(s+1));
printf(" %d\n",*(s+2));
printf(" \n\n");
return 0;
}
OUTPUT:
String are:
cricket
tennis
football
Starting locations of the string are:
134514112
134514120
134514127
s is a array of character pointers. s has three elements and each of them are storing the starting address of the string literals.i.e. s[0] is a pointer pointing to the starting address of "cricket". etc..
My question is :
By observing these addresses we can see that second string is stored just after the null character of the first string. All three strings are stored in sequential form. Is this always true ?

This is a linker decision - to store string literals tightly or not. There is no guaranties. Or even this may be done by compiler - it may create continuous data section that holds all involved literals. But nevertheless actual layout of that section is still implementation-specific and you shouldn't assume anything about it.

I have an example for you:
#include <stdio.h>
#include <inttypes.h>
char *s[] = { "ball", "football" };
int main( void )
{
int i;
for( i=0; i<2; i++ ) {
printf( "%" PRIuPTR "\n", (uintptr_t)s[i] );
// or printf( "%p\n", s[i] ); forr hex output
}
}
If I compile and run that program with gcc -O3 I get:
4195869
4195865
What happens here is that the optimizer merges both string literal to a single "football" so that s[0] becomes s[1] + 4.
That's only one example of what compiler / linker might decide on how to store string literals ...

It will be totally compiler dependent. Compiler can take any address at the time execution started

Only static arrays are contiguous in memory. ex: char s[1024].

Related

How to send data in hex on SerialPort

How to send data in hex on SerialPort?
I used this function, I receive the "yes, I can write to port" but I do not receive the data I entered
QByteArray send_data;
if(serialPort->isWritable())
{
qDebug()<<"Yes, I can write to port!";
int size = sizeof(send_data);
serialPort->write(send_data,size);
}
send_data += static_cast<char>(0xAA);
serialPort->write(send_data);
Data are transmitted in binary (essentially a sequence of 0 and 1). No matter what. Showing data in hexadecimal rather than a string of characters is just a choice.
In the following example, you can see that the array string_c is initialized with the same string that you are using in your code. Next, I print the data in both, as hex and as a string. You can see that the only difference is in the way I decided to print the data. The source data is the same for both.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
void printCharInHexadecimal(const char* str, int len)
{
for (int i = 0; i < len; ++ i) {
uint8_t val = str[i];
char tbl[] = "0123456789ABCDEF";
printf("0x");
printf("%c", tbl[val / 16]);
printf("%c", tbl[val % 16]);
printf(" ");
}
printf("\n");
}
int main()
{
char string_c[] = "Yes, i can write to port";
// string printed in hex
printCharInHexadecimal(string_c, 24);
// same string printed as "text"
printf("%s\n",string_c);
return 0;
}
You can see the above code running here: https://onlinegdb.com/Y7fwaMTDoq
Note: I got the function printCharInHexadecimal from here: https://helloacm.com/the-c-function-to-print-a-char-array-string-in-hexadecimal/
As suspected, your use of sizeof is wrong. It is not returning the size of the contained data, it is returning a non-zero constant that is the size of a QByteArray object itself. Since that object was freshly constructed it should be empty, and any size you use in the first write other than zero will lead to undefined behavior. Use:
int size = (int)send_data.size();
Skip the first write entirely, and use the above for your second write.
You need to be clear about what you expect. 0xAA in your source code is simply an integer value using hex representation. It complies to exactly the same code regardless of the source code presentation: 0xAA == 170 == 0263.
If you actually intended to output a string of characters at run time representing a value in hexadecimal, you need to convert that value from an integer to a string. For example;
char hexbyte[3] ;
sprintf( hexbyte, "%02X", 170 ) ;
serialPort->write(send_data) ;
will output ASCII characters AA, whilst demonstrating the equivalence of 170 to 0xAA. That is the hex notation in the source does not affect the value or how it is stored or represented in the compiled machine code.

Comparing chars stored in 2d arrays c++/c [duplicate]

I am trying to get a program to let a user enter a word or character, store it, and then print it until the user types it again, exiting the program. My code looks like this:
#include <stdio.h>
int main()
{
char input[40];
char check[40];
int i=0;
printf("Hello!\nPlease enter a word or character:\n");
gets(input); /* obsolete function: do not use!! */
printf("I will now repeat this until you type it back to me.\n");
while (check != input)
{
printf("%s\n", input);
gets(check); /* obsolete function: do not use!! */
}
printf("Good bye!");
return 0;
}
The problem is that I keep getting the printing of the input string, even when the input by the user (check) matches the original (input). Am I comparing the two incorrectly?
You can't (usefully) compare strings using != or ==, you need to use strcmp:
while (strcmp(check,input) != 0)
The reason for this is because != and == will only compare the base addresses of those strings. Not the contents of the strings themselves.
Ok a few things: gets is unsafe and should be replaced with fgets(input, sizeof(input), stdin) so that you don't get a buffer overflow.
Next, to compare strings, you must use strcmp, where a return value of 0 indicates that the two strings match. Using the equality operators (ie. !=) compares the address of the two strings, as opposed to the individual chars inside them.
And also note that, while in this example it won't cause a problem, fgets stores the newline character, '\n' in the buffers also; gets() does not. If you compared the user input from fgets() to a string literal such as "abc" it would never match (unless the buffer was too small so that the '\n' wouldn't fit in it).
Use strcmp.
This is in string.h library, and is very popular. strcmp return 0 if the strings are equal. See this for an better explanation of what strcmp returns.
Basically, you have to do:
while (strcmp(check,input) != 0)
or
while (!strcmp(check,input))
or
while (strcmp(check,input))
You can check this, a tutorial on strcmp.
You can't compare arrays directly like this
array1==array2
You should compare them char-by-char; for this you can use a function and return a boolean (True:1, False:0) value. Then you can use it in the test condition of the while loop.
Try this:
#include <stdio.h>
int checker(char input[],char check[]);
int main()
{
char input[40];
char check[40];
int i=0;
printf("Hello!\nPlease enter a word or character:\n");
scanf("%s",input);
printf("I will now repeat this until you type it back to me.\n");
scanf("%s",check);
while (!checker(input,check))
{
printf("%s\n", input);
scanf("%s",check);
}
printf("Good bye!");
return 0;
}
int checker(char input[],char check[])
{
int i,result=1;
for(i=0; input[i]!='\0' || check[i]!='\0'; i++) {
if(input[i] != check[i]) {
result=0;
break;
}
}
return result;
}
Welcome to the concept of the pointer. Generations of beginning programmers have found the concept elusive, but if you wish to grow into a competent programmer, you must eventually master this concept — and moreover, you are already asking the right question. That's good.
Is it clear to you what an address is? See this diagram:
---------- ----------
| 0x4000 | | 0x4004 |
| 1 | | 7 |
---------- ----------
In the diagram, the integer 1 is stored in memory at address 0x4000. Why at an address? Because memory is large and can store many integers, just as a city is large and can house many families. Each integer is stored at a memory location, as each family resides in a house. Each memory location is identified by an address, as each house is identified by an address.
The two boxes in the diagram represent two distinct memory locations. You can think of them as if they were houses. The integer 1 resides in the memory location at address 0x4000 (think, "4000 Elm St."). The integer 7 resides in the memory location at address 0x4004 (think, "4004 Elm St.").
You thought that your program was comparing the 1 to the 7, but it wasn't. It was comparing the 0x4000 to the 0x4004. So what happens when you have this situation?
---------- ----------
| 0x4000 | | 0x4004 |
| 1 | | 1 |
---------- ----------
The two integers are the same but the addresses differ. Your program compares the addresses.
Whenever you are trying to compare the strings, compare them with respect to each character. For this you can use built in string function called strcmp(input1,input2); and you should use the header file called #include<string.h>
Try this code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char s[]="STACKOVERFLOW";
char s1[200];
printf("Enter the string to be checked\n");//enter the input string
scanf("%s",s1);
if(strcmp(s,s1)==0)//compare both the strings
{
printf("Both the Strings match\n");
}
else
{
printf("Entered String does not match\n");
}
system("pause");
}
You need to use strcmp() and you need to #include <string.h>
The != and == operators only compare the base addresses of those strings. Not the contents of the strings
while (strcmp(check, input))
Example code:
#include <stdio.h>
#include <string.h>
int main()
{
char input[40];
char check[40] = "end\n"; //dont forget to check for \n
while ( strcmp(check, input) ) //strcmp returns 0 if equal
{
printf("Please enter a name: \n");
fgets(input, sizeof(input), stdin);
printf("My name is: %s\n", input);
}
printf("Good bye!");
return 0;
}
Note1: gets() is unsafe. Use fgets() instead
Note2: When using fgets() you need to check for '\n' new line charecter too
You can:
Use strcmp() from string.h, which is the easier version
Or if you want to roll your own, you can use something like this:
int strcmp(char *s1, char *s2)
{
int i;
while(s1[i] != '\0' && s2[i] != '\0')
{
if(s1[i] != s2[i])
{
return 1;
}
i++;
}
return 0;
}
I'd use strcmp() in a way like this:
while(strcmp(check, input))
{
// code here
}
How do I properly compare strings?
char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow
// insufficient
while (check != input)
// good
while (strcmp(check, input) != 0)
// or
while (strcmp(check, input))
Let us dig deeper to see why check != input is not sufficient.
In C, string is a standard library specification.
A string is a contiguous sequence of characters terminated by and including the first null character.
C11 §7.1.1 1
input above is not a string. input is array 40 of char.
The contents of input can become a string.
In most cases, when an array is used in an expression, it is converted to the address of its 1st element.
The below converts check and input to their respective addresses of the first element, then those addresses are compared.
check != input // Compare addresses, not the contents of what addresses reference
To compare strings, we need to use those addresses and then look at the data they point to.
strcmp() does the job. §7.23.4.2
int strcmp(const char *s1, const char *s2);
The strcmp function compares the string pointed to by s1 to the string pointed to by s2.
The strcmp function returns an integer greater than, equal to, or less than zero,
accordingly as the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2.
Not only can code find if the strings are of the same data, but which one is greater/less when they differ.
The below is true when the string differ.
strcmp(check, input) != 0
For insight, see Creating my own strcmp() function
#include<stdio.h>
#include<string.h>
int main()
{
char s1[50],s2[50];
printf("Enter the character of strings: ");
gets(s1);
printf("\nEnter different character of string to repeat: \n");
while(strcmp(s1,s2))
{
printf("%s\n",s1);
gets(s2);
}
return 0;
}
This is very simple solution in which you will get your output as you want.

Using char* to store data and error produced

const char* val1 = advertisedDevice.getAddress().toString().c_str();
Serial.printf("Advertised Device: %s \n", val1);
This code is used to retrieve the MAC address of a BLE device.
The output of val1 on the serial monitor is:
Advertised Device: 45:89:a2:d8:74:65
But when I try to output val1 individually the system crashes. The code is shown below. Why is this?
Serial.printf("Val is : %s", val1[0]);
I should expect the serial monitor is print out
Val is : 4
I am also trying to store val1 is a string array, so for example
pseudo-code
String arr[50];
loop{
const char* val1 = advertisedDevice.getAddress().toString().c_str();
Serial.printf("Advertised Device: %s \n", val1);
arr[i] = val1[0]+val1[1]+val1[2]+....+val1[18]
i++;
}
I want to store it in a single array because I then upload it to a database. I cant do this if its in the form of val1[0],val1[1]... and so on. It will be easier to store all the data in a single array location i.e.
arr[1] = "45:47:89:fd:12",
arr[2] = "47:AC:1b:24:58" and so on.
Is this right?
Serial.printf("Val is : %s", val1[0]);
%s expects a string of characters, i.e. a char * or const char * variable. val1 is a const char *, so val1[0] is a char that is the first character within val1. You need to change %s to %c, or else Serial.printf will believe the value of val1[0] is an address to a string of characters, causing a crash or undefined behavior.
If you meant for val1 to be an array of strings, you need to declare it as that. For example:
const char *val1[50];
val1[0] = advertisedDevice.getAddress().toString().c_str();
Serial.printf("Val is : %s", val1[0]); // Now this will work
Edit: If you're looking to build a list of strings out of arr, you should be able to simply assign to arr and access the strings through it:
String arr[50];
loop{
arr[i] = advertisedDevice.getAddress().toString().c_str();
// If above doesn't work, try: arr[i] = String(...);
Serial.printf("Advertised Device: %s \n", arr[i]);
i++;
}

Saving Char from lex to array of Char in C

I'm saving characters from a c file in this array
char *idTable[100];
Inside a while loop,
if(ntoken == 1){
idTable[numId] = yytext;
printf(" \nVariable %s", idTable[numId]);
printf(" Found\n");
numId++;
}
and then iterate through the array. The variable yytext is supposed to have only identifiers and variables like int i, int j, int cont
When I print those character inside the loop, it shows me the variables that I want to save. But when I iterate the array it takes all the text from the variable to the bottom:
while(i<numId){
printf("%d", i );
printf("%s", idTable[i]);
i++;
}
So,
printf(" \nVariable %s", idTable[numId]);
printf(" Found\n");
Will print characters like Variable i Found But printf("%s", idTable[i]); Will always print text inside from the file I want to see. Something like this:
i;
int j;
char c;
char cadena;
float z;
int 89aa12;
z=14.9e-8;
z= 3454y45hrthtrh;
z== 3454y45hrthtrh;
z= 3454y45hrthtrh;
z=12.9;
cadena="Hola";
scanf ("%d",i);
i=i*2;
printf ("El doble es %d",i);
Y="Cualquier Cosa 1";
u=z+y
You're saving a pointer to the same memory in each element of idTable, so whatever that memory is set to last is what each one will be pointing to.
You need to allocate additional memory for each string you want to save (or use a std::string).
strdup may do what you want.
idTable[numId] = strdup(yytext);
but don't forget to free that memory when you're done with it.

What is proper size of buffer when using sprint()?

What is proper size of an char array (buffer) when i want to use sprintf function?
I dont know why this part of code is working if buffer can hold only 1 char? I put a lot more chars inside than 1.
/* sprintf example */
#include <stdio.h>
int main ()
{
char buffer[1];
int n, a=5, b=3;
n = sprintf (buffer, "%d plus %d is %d", a, b, a+b);
printf ("[%s] is a string %d chars long\n", buffer, n);
return 0;
}
Results:
[5 plus 3 is 8] is a string 13 chars long
What is proper size of an char array (buffer) when i want to use sprintf function?
There isn't one.
If you can work out an upper bound from the format string and types of input, then you might use that. For example, a 32-bit int won't take up more than 11 characters to represent in decimal with an optional sign, so your particular example won't need more than 44 characters (unless I miscounted).
Otherwise, use something safer: std::stringstream in C++, or snprintf and care in C.
I don't know why this part of code is working if buffer can hold only 1 char?
It isn't. It's writing past the end of the buffer into some other memory.
Maybe that won't cause any visible errors; maybe it will corrupt some other variables; maybe it will cause a protection fault and end the program; maybe it will corrupt the stack frame and cause all kinds of havoc when the function tries to return; or maybe it will cause some other kind of undefined behaviour. But it's certainly not behaving correctly.
In your code a buffer overflow occurred, there were no apparent consequences, but that doesn't mean it worked correctly, try using a memory debugger like valgrind and you will see what I mean.
You can't ensure that sprintf() will not overflow the buffer, that's why there is a snprintf() function to which you pass the size of the buffer.
Sample usage
char buffer[100];
int result;
result = snprintf(buffer, sizeof(buffer), "%d plus %d is %d", a, b, a + b);
if (result >= sizeof(buffer))
{
fprintf(stderr, "The string does not fit `buffer'.\n");
}
Assuming code must use sprintf() and not some other function:
pre-determine the worse case output size and add margin.
Unless there are major memory concerns, suggest a 2x buffer. Various locales can do interesting things like add ',' to integer output as in "123,456,789".
#include <stdio.h>
#include <limits.h>
#define INT_DECIMAL_SIZE(i) (sizeof(i)*CHAR_BIT/3 + 3)
#define format1 "%d plus %d is %d"
char buffer[(sizeof format1 * 3 * INT_DECIMAL_SIZE(int)) * 2];
int n = sprintf(buffer, format1, a, b, a + b);
A challenging example is when code tries sprintf(buf,"%Lf", some_long_double) as the output could be 1000s of characters should x == LDBL_MAX. About 5000 characters with binary128 as long double.
// - 123.............456 . 000000 \0
#define LDBL_DECIMAL_SIZE(i) (1 + 1 + LDBL_MAX_10_EXP + 1 + 6 1)