Well , I was actually looking at strcmp() , was confused about its working . Anyways I wrote this code
#include <stdio.h>
main()
{
char a[5] = "ggod";
char b[5] = "ggod";
int c = 0;
c = b - a;
printf("%d value", c);
}
and I get the output as
16
Can anyone explain Why is it 16 ?
What you have subtracted there are not two strings, but two char *. c holds the memory address difference between a and b. This can be pretty much anything arbitrary. Here it just means that you have 16 bytes space between the start of the first string and the start of the second one on your stack.
c = b - a;
This is pointer arithmetic. The array names it self points to starting address of array. c hold the difference between two locations which are pointed by b and a.
When you print those values with %p you will get to know in your case
if you print the values looks like this a==0x7fff042f3710 b==0x7fff042f3720
c= b-a ==>c=0x7fff042f3720-0x7fff042f3710=>c=0x10 //indecimal the value is 16
Try printing those
printf("%p %p\n",a,b);
c=b-a;
if you change size of array difference would be changed
char a[120]="ggod";
char b[5]="ggod";
b is an array object
a is also an array object
an array object is a static address to an array.
so b-a is adifference between 2 addresses and not between the 2 strings "ggod"-"ggod"
If you want to compare between 2 string you can use strcmp()
strcmp() will return 0 if the 2 strings are the same and non 0 value if the 2 strings are different
here after an example of using strcmp()
Related
I have a little problem with PostgreSQL results and integer in C language. So I have a simple table with this structure :
ID(pk int) | name (text) | values (int)
1 | apple | 100
2 | banana | 9
I use this code :
PGconn *conn = PQconnectdb("user=un password=pw dbname=db hostaddr=1.2.3.4 port=5432");
res = PQexec(conn, "SELECT * FROM fruits WHERE name='banana'");
int *banan_count;
banana_count = (int)PQgetvalue(res, 0, 2);
printf ("Banana values : %u\n", banana_count);
PQclear(res);
do_exit(conn);
The problem is that my results isn't '9' when I try print out with 'banana_count', but when I print out 'PQgetvalue(res, 0, 2)' then I got '9', so I think I have a conversion problem, but I can't find a solution. So my question is that how can I convert 'PQgetvalue(res, 0, 2)' to integer variable in C proramming language? (I use Ubuntu 18.04 and for compile my fruits.c with gcc).
Thank you for the supports and helps.
In C, text is technically an array of chars, followed with a null-term. Roughly, array is a pointer to allocated memory of known size (syntax may vary widely). So let's see the code.
PGconn *conn = PQconnectdb("user=un password=pw dbname=db hostaddr=1.2.3.4 port=5432"); //No doubts. It's your professional area.
res = PQexec(conn, "SELECT * FROM fruits WHERE name='banana'"); //same thing.
//int *banan_count; //Aside the typo (banana_count), you don't need a pointer to int! PQgetvalue returns a pointer to char (roughly equal to array of chars, roughly equal to text, you'll learn differences later). This array keeps ONE int value in text form.
int banana_count_2; //That's what you need: a single int value. Not a pointer.
//banana_count = (int)PQgetvalue(res, 0, 2); //Wrong: you take the pointer to char, convert it few times and assign to your int* pointer. Pointer becomes technically valid, but it points to first group of characters, reading them as an integer value (probably char1 + char2*256 + char3*65536 ... depending on your platform). Of course, actual integers are not represented in text form in computer memory, so you get an absurdly huge value (even '0' character has code 48).
banana_count_2 = atoi(PQgetvalue(res,0,2)); //PQgetvalue allocates memory by itself, so the char* it returns points to a valid, allocated memory area. We can say it's an array filled with null-terminated text line, and give this line to atoi();
printf ("Banana values : %u\n", banana_count_2);
PQclear(res); //Good thing you didn't forget to unallocate the char array!
do_exit(conn);
Problem : Although I declared two char strings , whose contents are the same , Outputs are different.
#include <stdio.h>
int main(void)
{
/* Initialization of two different array that We deal with */
char arr1[10]={'0','1','2','3','4','5','6','7','8','9'};
char arr2[10]="0123456789";
/* Initialization End */
for(int i = 0 ; i < 11 ; ++i)
{
printf("arr1[%d] is %c \t\t",i,arr1[i]);
printf("arr2[%d] is %c\n",i,arr2[i]);
if(arr1[i]=='\0')
printf("%d . character is \\0 of arr1 \n",i);
if(arr2[i]=='\0')
printf("%d . character is \\0 of arr2 \n",i);
}
return 0;
}
Expectation : I expected that both if statements are going to be true for any kind of value of 'i'.
Output : It is an output that I got it.
arr1[0] is 0 arr2[0] is 0
arr1[1] is 1 arr2[1] is 1
arr1[2] is 2 arr2[2] is 2
arr1[3] is 3 arr2[3] is 3
arr1[4] is 4 arr2[4] is 4
arr1[5] is 5 arr2[5] is 5
arr1[6] is 6 arr2[6] is 6
arr1[7] is 7 arr2[7] is 7
arr1[8] is 8 arr2[8] is 8
arr1[9] is 9 arr2[9] is 9
arr1[10] is 0 arr2[10] is
10 . character is \0 of arr2
Both cases invoke undefined behavior by accessing the array out of bounds. You cannot access index 10 of an array with items allocated from index 0 to 9. Therefore you need to change the loop to i<10 or anything might happen. It just happened to be different values printed - because you have no guarantees of what will be printed for the byte at index 10.
In both examples, there is no null terminator, so they are equivalent. Due to a subtle, weird rule in the C language (C17 6.7.9/14 emphasis mine):
An array of character type may be initialized by a character string literal or UTF−8 string
literal, optionally enclosed in braces. Successive bytes of the string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
Normally when trying to store too many initializes inside an array, we get a compiler error. But not in this very specific case with a string literal initializer, which is a "language bug" of sorts. Change to char arr2[9]="0123456789"; and it won't compile. Change to char arr2[11]="0123456789"; and it will work just fine, even when iterating over 11 elements.
There are a few small things wrong with your code and the assumptions you seem to make about it.
1. These two declarations are not the same
char arr1[10]={'0','1','2','3','4','5','6','7','8','9'};
char arr2[10]="0123456789";
The second line is equal to this:
char arr2[10]={'0','1','2','3','4','5','6','7','8','9', 0x00};
... which defines an array containing 11 elements. Check out implicit zero-termination for string literals.
EDIT:
I'm getting quite a lot of down-votes for this point specifically. Please see Lundin's comment below, which clarifies the issue.
2. Your for-loop iterates over 11 elements
for(i=0 ; i<11 ;++i)
The loop above goes through i = 0..10, which is 11 elements.... but you only wanted to compare the first 10 right?
You could change your loop to only compare the first ten elements [for(i = 0; i < 10; ++i)] and that would make your program work as you expect.
Because of what it seems you are assuming, I would recommend reading up on strings in C, array-indices and undefined behavior.
when a character array is initialized with a double quoted string and array size is not specified, compiler automatically allocates one extra space for string terminator ‘\0’
Ref
Hi i came across with this simple c program but i cant understand how this code works:
#include <string.h>
#include <stdio.h>
char *a = "\0hey\0\0"; /* 6 */
char *b = "word\0up yo"; /* 10 */
char *c = "\0\0\0\0"; /* 4 */
int main(void)
{
char z[20];
char *zp = z;
memcpy(zp, a, strlen(a)+1);
memcpy(zp, b, strlen(b)+1);
memcpy(zp, c, strlen(c)+1);
/* now z contains all 20 bytes, including 8 NULLs */
int i;
for(i = 0; i < 20; i++){
if (z[i] == 0){
printf("\\0");
}
printf("%c", z[i]);}
return 0;
}
I was expecting that printing z the output would be :
\0hey\0\0\0word\0up yo\0\0\0
But instead I am getting :
\0ord\0\0\0\0\0\0\0\0\0\0\0\0???Z
Finally , when i print a instead of z i get the right output.
Can anyone explain to me why this happens ? Thanks in advance.
EDIT: How i could concatenate such strings?
Strings in C are zero-terminated; the functions in the standard C library assume this property. In particular, the function strlen returns the number of non-zero characters from the start of the string. In your example, strlen(a) is equal to 0, already as the first character of a is zero.
The code will have the following effect:
memcpy(zp, a, strlen(a)+1);
Now zp still contains \0, because strlen(a) is 0, so 1 character is copied.
memcpy(zp, b, strlen(b)+1);
Now zp contains word\0: five characters copied.
memcpy(zp, c, strlen(c)+1);
Now just the first character of zp is overwritten, so it contains \0ord\0.
Finally , when i print a instead of z i get the right output. Can anyone explain to me why this happens ? Thanks in advance.
That's because a, b, and c happen to be allocated sequentially in the memory. When you print "20 bytes starting from the start of a", you're actually looking at the memory past the latest byte of a. This memory happens to contain b. So you actually start reading b. Same goes for b and c. Note that this is by no means guaranteed. Looking past the memory allocated for a char * is in fact an instance of undefined behaviour.
How i could concatenate such strings?
In general, there is no way how to find the length of such "strings" in the runtime. I would not call them strings as such, since "string" has a specific meaning in the C language - it refers to zero terminated strings, while your's are simply regions of memory.
However, since you know the size at compile time, you can use that. To avoid magic numbers in the code, it's better to use char arrays instead of char pointers, because then you can use the sizeof operator. However, note that all string literals in C are implicitly zero terminated! To fit the result in the 20-byte buffer, you'll want to use sizeof(x) - 1:
char a[] = "\0hey\0\0"; /* 6 */
char b[] = "word\0up yo"; /* 10 */
char c[] = "\0\0\0\0"; /* 4 */
memcpy(zp, a, sizeof(a) - 1);
zp += sizeof(a) - 1;
memcpy(zp, b, sizeof(b) - 1);
zp += sizeof(b) - 1;
memcpy(zp, c, sizeof(c) - 1);
I was tried to print values of a float array with 7 elements. I assigned only 3 values and they are belong to float, double and integer.
Code:
#include <stdio.h>
int main(){
float array [7];
float f = 3.24;
double d = 23.5;
int i = 4;
array[0] = f;
array[1] = i;
array[2] = d;
int n = sizeof(array)/sizeof(float);
printf("Number of Elements : %d \n\n\n",n);
for(int j = 0; j < n ; j++){
printf("%.2f ,",array[j]);
}
printf("\b ");
}
I got an output as follows :
Number of Elements : 7
3.24 ,4.00 ,23.50 ,-1.#R ,96627196995476105000000000000000.00 ,96629547147269436000000000000000.00 ,0.00
I want to clear is my code correct? And why last four values are different to each other. What are these values?
The last values are known as garbage values in C.
If you do not initialize a variable explicitly in C, it's value could be anything before you explicitly assign something to it. This anything could be garbage; the language standard does not specify what it should be.
You can read this blog for How C compiler decides garbage values: http://blog.aditech.info/2008/02/how-c-compiler-decides-garbage-values.html.
First.
Yes, your code is correct (add return 0 command at the end of your main() function though). However, it needs to be more specific, which leads to your second question.
Second.
C is a language that allows a programmer to do lots of things, but it also requires the programmer to do lots of manual coding.
So, when you declare an array of 7 items, C compiler marks a region of memory to accommodate those items (in this case of the type of float). But it doesn't actually check what that region of memory contains until you explicitly assign the values. In your case the last four values (which you have not assigned yourself) are just garbage left in the region of memory marked for your array.
Once again, compiler does not clear the memory for you when you declare the array, it just marks the region of memory. It's your responsibility to assign default values to the array.
Your possible solution is to manually initialize all of the elements of your array to some default value (for example, a 0), like this:
float array[7] = {0}
I have programming exam soon, and I still can't understand some things, could you guys help me?
Basically, we got:
char *nap[]= {"Reklamacja","Perspektywa","Reinkarnacja","Hermengilda","Audytorium","Mineralogia","Frustracja"}
Those are bunch of words in Polish language, but they doesn't matter at all.
So moving on, we have:
Size of char type on this PC : 1
Size of long type on this PC : 4
Address of beginning nap array (char type): 0x22ff20
Address of R letter in word "Reklamacja": 0x47575d,
Address of P letter in word "Perspektywa": 0x475768,
Address of R letter in word "Reinkarnacja": 0x475774,
Address of H letter in word "Hermengilda": 0x475781,
Address of A letter in word "Audytorium": 0x47578e,
Address of M letter in word "Mineralogia": 0x475799,
Address of F letter in word "Frustracja": 0x4757a5
The question is: what is the effect of the following line of code?
printf("%#lx", nap+5);
The correct answer is: 0x22ff34
Why is it like so and not like 0x22ff20 + 5 which is 0x22ff25?
The answer is the same for any typed pointer value in C, and uses a language feature called pointer arithmetic.
What is the byte-width of the element type, including padding if a struct or union type?
Multiply by the index N you're using
Add to the base address of the array.
The result should be the address of the N'th element in the sequence. Note you cannot portably do this with void*, and any cast you perform on the pointer prior to performing the operation will affect the outcome.
In your case, the element type of your array is char *. Assuming sizeof(char*) == 4 on your platform then
4 bytes
4 * 5 = 20 bytes (0x14)
0x22ff20 + 0x14 = 0x22ff34
Remember, an array expresses as pointer-to-type with a value of the array base-address when used in the above calculation. It may seem trivial, but that is routinely the part of this that is missed.
Best of luck
nap is a pointer to the first item of the array: nap == &(nap[0]).
nap+5 is a pointer to the sixth item of the array: nap+5 == &(nap[5]).
Each item of your array is 4 bytes long (test for sizeof(char *)), so the numerical value of nap+5 is a numerical value of nap plus 5 times 4:
0x22ff20 + 4*5 = 0x22ff20 + 0x14 = 0x22ff34
Your nap variable is declared as a pointer to an array of strings. So when you are using nap+5 you are really moving the pointer 5 elements down the array (which will point to Mineralogia). In order to retrieve the result that you were expecting, you will have to cast the pointer so it will point to the first string, then add 5 to it to move the pointer 5 characters down. Here is a test application that I wrote up to demonstrate this (my code usually explains better than I can verbally lol):
#include <stdio.h>
int main()
{
char* nap[] = {"Reklamacja","Perspektywa","Reinkarnacja","Hermengilda","Audytorium","Mineralogia","Frustracja"};
//Returns the beginning address of nap
printf("%#lx\r\n", nap);
//Returns the sixth string in nap (aka nap[5] since arrays are 0-based index)
//and the address
printf("%s %#lx\r\n", *(nap+5), nap+5);
//Returns the first string in the array (aka nap[0]) and the address
printf("%s %#lx\r\n", *nap, *nap);
//Returns the 1st string in the array starting at the 6th letter and the address
printf("%s %#lx\r\n", *nap+5, *nap+5);
return 0;
}
Also remember that a char is 4 bytes so the last printf statement moved the pointer 20 bytes down the string.