#include<stdio.h>
int main(){
char *names[2] = {"Lord", "Voldemort"};
printf("%s %s\n",names[0], names[1]);
return 0;
}
Why is the above code working? I mean, it should print the addresses of the strings it is containing in their respective indexes and we should be using *names[0] and *names[1]. But why it is working though?
If you had an array of integers like
int values[2] = { 1, 2 };
then what would you get if use used e.g. values[1]? You would get the second element in the array. Printing this values array would be done like
printf("%d %d\n", values[0], values[1]);
You are with me this far?
Now back your array. If you use names[1] what do you get then? You still get the second element in the array. And what is the second element? It is a pointer to char (i.e. char *). And what can a pointer to char be used as? A string.
And the "%s" format with printf expects a string, a char * more specifically. Which is just what you give as arguments.
If you use the dereference operator like *names[1] then thanks to operator precedence it is equal to *(names[1]) which is equal to names[1][0]. In other words it gives you the first character in the string pointed to by names[1].
names[0] and names[1] are both const char* types.
When you use %s with a const char* argument, printf outputs the characters starting at the beginning of the argument, until \0 is reached.
If you want the addresses then use
printf("%p %p\n", (const void*)names[0], (const void*)names[1]);
Related
I am really struggling with pointers in C. Specifically, I have been having trouble understanding how to work with pointers when they are in main versus when I input a pointer into a function parameter from main.
I have a few scenario questions about them that hopefully someone can answer:
int main (int argc, char* argv[]) {
int x = 7;
int* num = 4;
char* word = "johnny";
//Q1. how do I get the address of 'num'?
//Q2. how do I get the address of 'x'? (should I be using x's or num's address?)
//Q2. how do I get the value of 'num'?
//Q3. how do I get the address of 'word'?
//Q4. how do I get the whole string for 'word'?
//Q5. how do I get an individual character in 'word'? (for index 0 ('j') and index 3 ('n'))
}
bool some_func (int* count, char** name) {
//Q6. how do I get the address of the inputted 'count'?
//Q7. how do I get the value of the inputted 'count'?
//Q8. how do I get the address of the inputted string 'name'?
//Q9. how do I get the whole string of the inputted string 'name'?
//Q10. how do I get an individual character of the inputted string 'name'? (for index 0 ('j') and index 3 ('n'))
}
For my recent homework assignments, I've been given intimidating headers like these and I don't know how to get the values that I want out of them. Say I found out that saying '*name' got me the whole string, where do I go from there?
If someone could answer all of the questions in the code I think that would probably be the best way of learning it since it's through example. Thanks!
Firstly, when you declare int* num, you created a pointer. You cannot assign a value directly to a pointer. What you could do is declare a variable, like you did for int x, and point the pointer to variable x (hence the name pointer) by using num = &x (&x refers to address of x, and is assigned to num) To get the value of num, you will have to use *num. Below is an example:
int *num;
int a = 4;
num = &a;
printf("address of a is %p, and value of a is %d", num, *num);
Output to first example:
address of a is <0xsome address> , and value of a is 4
As for characters, same thing you can't assign a value directly to pointer (like you did in char* word = "johnny";. A concept I think you should know is that "johnny" is a String, and strings are essentially an array of characters, hence each character of the string has its own address. Using similar to previous example:
char* word;
char someString[6] = "johnny";
word = &someString[0];
printf("address of first char of someString is %p, 1st char of someString is %c, 2nd char of someString is %c", word, *(word), *(word+1));
Output for the second example:
address of first char of someString is <0xsome address>, 1st char of someString is j, 2nd char of someString is o
Importing thing to note is that when accessing each character of the string using de-referencing of pointers, the +n must be inside the bracket with the pointer word.
*word+1 //WRONG
*(word+1) //CORRECT
Hope this gives you a base foundation of what you will need to tackle the rest of the questions!
I'm new to C and pointers, so i have this problem. I want to tell to pointer how much memory it should point to.
char * pointer;
char arr[] = "Hello";
pointer = arr;
printf("%s \n", pointer);
This pointer will point to whole array, so i will get "Hello" on the screen. My question is how can i make pointer to only get "Hel".
You may try this:
char * pointer;
char arr[] = "Hello";
pointer = arr;
pointer[3] = '\0'; // null terminate of string
printf("%s \n", pointer);
If you always work with strings, then have a look at strlen for getting length of a string. If a string arr has length l, then you may set arr[l/2] = '\0', so that when you print arr, only its first half will be shown.
You may also want to print the last half of your string arr? You can use pointer to point to any place you want as the start. Back to your example, you may try:
char * pointer;
char arr[] = "Hello";
pointer = arr + 2; // point to arr[2]
printf("%s \n", pointer);
Have a check what you will get.
printf has the ability to print less than the full string, using the precision value in the format string. For a fixed number of characters (e.g. 3), it's as simple as
printf( "%.3s\n", pointer );
For a variable number of characters, use an asterisk for the precision, and pass the length before the pointer
int length = 3;
printf( "%.*s\n", length, pointer );
You don't know what a pointer is so I'll explain.
A pointer does not point to a string. It points to a char! Yes, a char. A string in C is really just a set of chars all one after the other in the memory.
A char* pointer points to the beginning of a string. The string ends when there is a '\0' (aka null) char. When you printf("%s",s), what printf does is a cycle like this:
int i;
for(i=0;1;i++) //infinite cycle
{
if(s[i]=='\0')
break;
printf("%c",s[i]);
}
Meaning it will not print a string but all the chars in a char array until it finds a null char or it goes into memory space that is not reserved to it (Segmentation fault).
To print just the 1st 3 characters you could do something like this:
void printString(char* s,int n) //n=number of characters you want to print
{
if(n>strlen(s))
n=strlen(s);
else if(n<0)
return;
char temp=s[n]; //save the character that is in the n'th position of s (counting since 0) so you can restore it later
s[n]='\0'; //put a '\0' where you want the printf to stop printing
printf("%s",s); //print the string until getting to the '\0' that you just put there
s[n]=temp; //restore the character that was there so you don't alter the string
}
Also, your declaration of pointer is unnecessary because it is pointing to the exact same position as arr. You can check this with printf("%p %p\n",arr,pointer);
How much of the string is printed is controlled by the NULL-character "\0", which C automatically appends to every string. If you wish to print out just a portion, either override a character in the string with a "\0", or use the fwrite function or something similar to write just a few bytes to stdout.
You could achieve the objective with a small function, say substring.
#include<stdio.h>
#include<string.h> // for accessing strlen function
void substring(char* c,int len)
{
if (len <= strlen(c)){
*(c+len)='\0';
printf("%s\n",c);
}
else{
printf("Sorry length, %d not allowed\n",len);
}
}
int main(void)
{
char c[]="teststring";
char* ptr=c;
substring(ptr,4); // 4 is where you wish to trim the string.
return 0;
}
Notes:
In C++ a built-in function called substring is already available which shouldn't be confused with this.
When a string is passed to a function like printf using a format specifier %s the function prints all the characters till it reaches a null character or \0. In essence, to trim a string c to 4 characters means you put c[4] to null. Since the count starts from 0, we are actually changing the 5th character though. Hope the example makes it more clear.
int main()
{
int i;
char *names[5] = {"Miri", "Tali", "Ronit", "Avigail", "Shlomit"};
//Printing all the names:
for (i=0; i<5; i++)
printf("%s\n" , names[i]);
return 0;
}
How come its print the whole name? does names[0] (for example) shouldn't print only M?
names is array of character pointers. So names[0] is char * pointing to "Miri".
And similarly for other subsequent items.
In your program names is an array of pointers to char as already was mentioned in Rohan's answer, so to print the first character you should first access the array element and then the the 0th character
printf("%c\n", names[i][0]);
also note that the appropriate specifier is "%c" for one character, since "%s" expects a pointer to char, which should point to a null terminated sequence of bytes, i.e. a string.
Aditionally you should declare the array like
const char *names[5] = {"Miri", "Tali", "Ronit", "Avigail", "Shlomit"};
because the elements are string literals, and should not be modified. So using the const specifier you prevent acidentally doing that.
I have a doubt in my program
#include<stdio.h>
int myFunc(char **);
main()
{
char *a[2]={"Do","While"};
myFunc(a);
}
int myFunc(char **P)
{
/* Here I want to print the strings passed but I'm unable to
print the strings I just tried the below statement which
printed just the first letter which is 'D'*/
printf("%c",**P);
}
when i tried
printf("%s",**P);
I am getting run time error. so can anyone please help me out?
Thanks
Madhu
Put size as parameter to allow the function to know how many strings you have in your array. Then, you should iterate the array and print each one.
int myFunc( char** p, int size)
{
for( int i = 0; i < size; ++i)
{
printf("%s", p[i]);
}
}
Later edit (as requested :-) )
int main( int, char**)
{
char *a[2]={"Do","While"};
myFunc( a, 2); // Could be myFunc( a, sizeof(a)/sizeof(char*));
// ...
return 0;
}
Too many stars - try
printf("%s",*P);
And you need %s format specifier - %c is just for single character.
If you want to print all strings, you need to pass number of strings in array and then print these strings from the loop.
Check the code suggested by Cătălin Pitiș. To pass the number of strings, you call function like this:
myFunc(a, sizeof(a)/sizeof(a[0]));
for( int i = 0; i < 2; i++ ) {
char* string = P[i];
printf( "%s", string );
}
And you shoud use some way of passing size of array into the function - either pass it as an int parameter,
int myFunc(char **P, int size)
{
for( int i = 0; i < size; i++ ) {
//whatever here
}
}
or always append a zero value to the array and only loop until you find that zero value.
char* array[] = { "String1", "String2", 0 };
Otherwise you will have hard to maintain code.
I like objective-c style nil (0) terminated arrays:
void myFunc(char **P)
{
while (*P) // loop to iterate over all strings until 0
printf("%s\n",*P++); // print and move to next element in array
}
int main()
{
char *a[]={"Do","While",0}; // added 0 to null terminate array,
myFunc(a); // kind of like string
}
Output:
Do
While
First, the good news: the type of a is equivalent to char **, so you are passing a valid parameter to myFunc().
The first problem is that %c is a format specifier that means print a single character. Since **P is an expression that evaluates to a single character, your first version does exactly what you told it to do. That isn't what you want.
The second version is close to syntactically correct. It should read printf("%s", *P), where *P is an expression that evaluates to a pointer to a nul-terminated ASCII string. In this case, it evaluates to "Do". This version won't print both strings.
Although it is true that the name of an array is the same as a pointer to its first element, that is a kind of "lie to students". Passing an array to a function does not and cannot convey the length of the array. To do that, you need either a second argument containing the length, or a convention like the nul-terminator on a string to indicate the end of the array. With that change, you can modify myFunc() to use a loop over the elements passed and print each one.
The problem in your code is that you want to print a string (char*) but you're giving it a char. Remember that P is an array of char*. When you de-reference it once, you get a char*; when you do it a second time, you just get the char at the beginning of the char*.
When you try to use the char value with the %s specifier, it treats the value as a pointer, and tries to dereference that value. Hence, it will try to print the "string" at the memory location X, where X is the value of the char (i.e. a value from 0 to 255). This gives you an access violation/segmentation fault (the error you see at runtime).
The best workarounds for this, as noted by Cătălin Pitiș and RBerteig, are to either:
pass another parameter to specify the length of the array
add an additional null at the end of the array.
if you don't want to keep and pass around array size::
int myFunc(char **);
main()
{
char *a[2]={"Do","While", NULL};
myFunc(a);
}
int myFunc(char **P)
{
if( !P )
return 0;
while(*P != NULL)
{
printf("%s",*P);
P++;
}
}
Wrong Answer: I think you may have to dereference P when you print it, although I could be wrong.
EDIT: I'm tired, it's 3 am here but I don't feel like sleeping so I'm here trying to answer questions. After reading the criticism, I reread the question and noticed that he does dereference P, but as is stated in another answer, it's dereferenced too much. When one wants to print a char string, one wants to pass a pointer as the char string is really an array.
Another EDIT: I would also like to point out that the person who asked the question made an edit after I answered and that when I first answered it didn't read "printf("%s",**P);" it read "printf("%s", P);" and the last part was bold.
I am practicing using pointers.
I have a pointer to an array of 3 strings: "dog", "cat", "rat".
I can print the contents using a for loop and using an array.
However, I am having problems printing them using pointer arithmetic. I would like to increment the pointer to the next element in the array. However, all it does is print the dog letters.
Code:
int main(int argc, char **argv)
{
char *str[3] = { "DOG", "CAT", "RAT"};
int i = 0;
/* display using an array element */
for(i = 0; i < 3; i++)
{
printf("str: %s\n", str[i]);
}
/* display using a pointer arthimatic */
while((*str)++)
{
printf("str: %s\n", str);
}
getchar();
return 0;
}
How can I accomplish this?
Edit:
Code:
while(str)
{
printf("str: %s\n", *(str++));
}
However, I get this error message. Doesn't the I-value have to be a variable of some sort?
error C2105: '++' needs l-value
You first have to get a pointer, and you would need a condition when to stop. A last NULL pointer can be used for that. So the code becomes
char *str[] = { "DOG", "CAT", "RAT", NULL };
char **elem_p = str;
/* display using a pointer arthimatic */
while(*elem_p) {
printf("str: %s\n", *elem_p);
elem_p++;
}
What you did was to increment the pointer stored in the array's first element. That pointer will never too soon equal to a null pointer (if at all), So, the loop will not stop until that pointers' internal value overflows or something else happens so that it equals to a null pointer. Then, you pass a pointer to the arrays first element to printf (you pass the array, but the compiler will convert it to a pointer - see below). Printf will interpret the bytes of those pointers as characters and print them, which will result in garbage printed out if it doesn't crash right away.
You want to increment at a higher level instead: Increment not one element (pointer) of the array, but the pointer to the elements itself. Now, you can't do
str++
Because str is an array. It's not a pointer, even though it can be converted to a pointer, which will then point to the first element of it. So, we create a pointer which points to str[0] initially, but increment it all again. Note that we increment it after printing, so that we print out the first element too.
Actually, i think i should explain why you can't do str++. Well, str is an array. An array is an object that occupies some fixed amount of storage. Above, the array occupies 4 times the size of a char pointer, 4 * sizeof(char*). What looks like a pointer at the first glance is a block of elements of the same type. For addressing elements, the compiler can make up a pointer out of an array in expressions, which then can be used to address elements in the array. If you do str++, the compiler will create a pointer for you. But that pointer is temporary, exists only for a short while for the sole purpose of immediately doing something with it, but it can not be changed like being incremented. That is the reason that we create a real pointer variable that we then can increment.
The problem with your code is that you're incrementing the dereferenced pointer str, which gives you a char * to the first element in the array (ie, dog).
You should be incrementing str itself, not what it points to.
However your loop termination check won't work in that case as there is no element in the array at the moment for which str == 0 holds true. In order to get that to work, you'll need to add a fourth element to the array that is 0.
str, being an array, cannot be incremented.
Right now, you're incrementing (*str), which is str[0]: the first element of that array. Since this element is a pointer, you're incrementing the pointer, making it reference the subsequent elements of the string "DOG".
What you need is a pointer that can point to (and thus walk over) str's elements. Since the elements are char*, the pointer to them would be char** - a double pointer.
(*str)++
Increments the value pointed to by s. You will need to increment the pointer itself and print the value of the pointee. Note, that str is not a l-value and you cannot increment it either.
Also, if you increment first, then you are left with only two legal strings that you can print. You invoke UB after that.
Try this:
int main(void)
{
/* we have added a sentinel to mark the end of the array */
char *str[] = { "DOG", "CAT", "RAT", 0 };
/* since str is an array, you cannot use it to loop, have a walker */
char **w = str;
/* display using a pointer arthimatic */
while(*w)
{
printf("str: %s\n", *w++);
}
return 0;
}
Look up operator precedence and binding in C.
while((*str)++)
{ printf("str: %s\n", str); }
This increments *str which is the letter 'd'. You don't want to do that. You want to increment the pointer. This code should do what you want:
while((str)++)
{ printf("str: %s\n", str); }