Print an element of 2D array of character or string? - c

main()
{
char str[][3]={"ab","cd","ef","gh"};
printf("\n%s\n%s",str[2][0],&str[0][0]);
//WHY WE NEED TO PUT "&" TO PRINT &str[2][0] the element.
}
//while this works properly
main()
{
char str[][3]={"ab","cd","ef","gh"};
printf("\n%s\n%s",str[2],&str[0]);
}

str[2] is the third element of array str. It is in turn a character array that has type char[3]. In function call like this
printf( "%s", str[2] );
the array is converted to pointer to its first character (element). The first character of array str[2] can be gotten like str[2][0]. So its address is determined like &str[2][0].
Thus expressions str[2] and &str[2][0] are equivalent.
As for this call
printf("\n%s\n%s",str[2],&str[0]);
then it is invalid. Format specifier %s expects an argument of type char * while the type of expression &str[0] is char **. However because in any case expression &str[0] has the value that is the address of the first element of array str[0] the function produces the correct result.
If you want to ouput only a single character instead of a string you have to use format specifier %c For example
printf("\n%c\n%s",str[2][0],&str[0][0]);
^^^
In this function call as str[2][0] is a single character then there is used format specifier %c for its output.

Related

Difficult time understanding string pointers in C

I am looking to learn C and having a really hard time grasping the concepts of string pointers (and just pointers in general).
I have the following program:
#include<stdio.h>
#include<string.h>
int main()
{
// char test[6] = "hello";
char *test = "hello"; // test is a pointer to 'h'
int size_of_test_pt = sizeof(test); // this is the size of a pointer? which is 8 bytes.
int size_of_test = sizeof(*test); // this is the size of h, which is 1.
printf("\nSize of pointer to test: %d\n", size_of_test_pt); // prints 8
printf("\nSize of test: %d\n", size_of_test); // prints 1
printf("\nPrint %s\n", test); // why does this print 'hello', I thought test was a pointer?
printf("\nPrint %c\n", *test); // this is printing the first character of hello, I thought this would print hello.
printf("\nPrint %i\n", *test); // this prints 104...is this ASCII for h
return 0;
}
Everything makes sense until the last 3 print statements. If test is a pointer variable. Why does printf print out the word "hello" rather than an address?
For the printf("\nPrint %c\n", *test) call is it the right understanding that I am dereferencing test, which is an address and accessing the first element, then printing it to the screen?
The conversion specifier %s is designed to output strings and it expects as an argument a pointer expression of the type char * or const char * that points to the first character of a string that to be outputted.
In this case the function outputs all characters starting from the address pointed to by the supplied pointer until the terminating zero character '\0' is encountered.
If you want to output the value of such a pointer you need to write
printf("\nPrint %p\n", ( void * )test);
The conversion specifier %c is designed to output a single object of the type char.
Pay attention to that the pointer test points to the first character of the string literal "hello". So dereferencing the pointer you will get the first character of the string literal.
Here is a demonstration program.
#include <stdio.h>
int main( void )
{
char *test = "hello";
for ( ; *test != '\0'; ++test )
{
printf( "%c ", *test );
}
putchar( '\n' );
}
The program output is
h e l l o
The string literal is stored in memory as a character array containing the following elements
{ 'h', 'e', 'l', 'l', 'o', '\0' }
If test is a pointer variable. Why does printf print out the word "hello" rather than an address?
In short, it's because the %s expects its parameter to be of type char *.
For the printf("\nPrint %c\n", *test) call is it the right understanding that I am dereferencing test, which is an address and accessing the first element, then printing it to the screen?
Yes. The %c format specifier expects its parameter to be a char, and that's exactly what you get when you dereference a pointer to char. Furthermore, it knows to print that value as a character. In the following line, the %i parameter expects value of type int, and since char is a kind of int, it accepts that and prints the numeric value of the character (h) that you provided.
In C a "string" is a sequence of characters, e.g. h, e, l, l, o. To indicate that the sequence is ending, the special value 0 is appended to the sequence.
If there were no such things as pointers, passing a string to a function would involve copying the entire sequence of characters. This is normally not practical, so instead we just pass on a reference (i.e. a pointer) telling where to find the first character of the string.
This is so commonly used that the pointer itself is sometimes referred to as a string even though it is really a pointer to a string. The string itself is the sequence of characters.
Think of a pointer like a bibliographic reference identifying a particular book. Including such a reference in a text is much more practical than inserting a copy of the entire book.

what is the explaination of the output of the given program

char *ptr = "helloworld"; printf(ptr);
Why it is printing helloworld as i haven't used *ptr in printf which should give the value like we use for pointer to an integer.
According to me it should we printf(*ptr) in printf
For any pointer or array p and index i, the expression p[i] is exactly equal to *(p + i).
If the index i is zero, then we have p[0] being exactly equal to *(p + 0). Adding zero to anything is a no-operation, so it's *(p). And the parentheses are not needed here which gives us *p.
So in your case *ptr would be the same as ptr[0], which is the first character in the string. And only the first character in the string, with the type char.
A "string" is a null-terminated sequence of characters, and to use it we have a pointer to the first character. Which is what plain ptr (without dereference) is. And that matches the printf format string argument, which needs to be a pointer to the first character in the null-terminated string.
printf expects its first argument to be a pointer to char:
7.21.6.3 The printf function
Synopsis
1 #include <stdio.h>
int printf(const char * restrict format, ...);
C 2011 Online Draft
so
printf( ptr );
is correct1. However, the usual practice for printing a plain text string is to do something like
printf( "%s\n", ptr );
rather than passing it as the format string. Alternately, you could use the puts function:
puts( ptr );
since no formatting is involved.
The value in ptr is the address of the first character of the string - printf will print the sequence of characters starting at that address until it sees the string terminator2.
You can pass a char * argument to a function that expects a const char *, but not the other way around; you'll get a diagnostic on the order of "argument n discards const" or something like that. The restrict keyword in the function declaration is basically an optimization hint - you don't need to worry about that right now.
If it sees a conversion specifier in the format string like %d or %f, it will take the value of the corresponding argument and format it as the equivalent sequence of characters.

why printf doesn't accept a pointer as an argument

why codeblocks crashes when I try to run this code :
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
char *ch= "Sam smith";
printf("%s\n",*ch);
}
but it works fine when I remove *ch in printf and replace it with just ch like this
void main(void)
{
char *ch= "Sam smith";
printf("%s\n",ch);
}
shouldn't *ch mean the content of the address pointed to by ch which is the string itself, and ch mean the adress of the first element in the string? so i expected the opposite!
I use Code blocks 17.12, gcc version 5.1.0, on windows 8.1 .
*ch dereferences the pointer to yield the data it points to. Here the first character of the string.
Providing the wrong specifier to printf is undefined behaviour (passing a value where printf expects a pointer)
printf("%c\n",*c);
would print the first character, without crashing. If you want to print all the string using %c (or use putchar), loop on the characters. But that's what %s does.
As a side note, better use const to reference literal strings so no risk to attempt to modify them:
const char *ch= "Sam smith";
why codeblocks crashes when I try to run this code :
char *ch= "Sam smith";
printf("%s\n",*ch);
ch is of type char *.
The %s conversion specifier expects a char *.
You pass *ch, which is the dereferenced ch, i.e. of type char.
If conversion specifiers do not match the types of the arguments, bad things (undefined behavior) happens.
shouldn't *ch mean the content of the address pointed to by ch which is the string itself
There is no data type "string" in C, and thus no "pointer to string".
A "string", in C parlance, is an array of characters, or a pointer to an array of characters, with a null-byte terminator.
ch is a char *, a pointer to the first character of that array - a string, so to speak.
*ch is a char, the first character of that array.
In C, You do not dereference a pointer to a string, when you want to use the whole string the pointer points to. This dereferencing process would result in the first character of the respective string, which is not what you want.
Furthermore, it is undefined behavior if a conversion specifier does not match to the type of the relative argument.
Thus,
printf("%s\n",*ch);
is wrong. *ch is the first character in the string, in this case S, of type char but the %s conversion specifier expects an argument of type *char.
printf("%s\n",ch);
is correct. ch is of type *char as required by the conversion specifier %s.
So, Codeblocks "crashes" apparently because of the mismatching argument type.

Pointer to a string and the difference between assignment and dereferencing

In the following code:
#include <stdio.h>
int main(void) {
char* message = "Hello C Programmer!";
printf("%s", message);
return 0;
}
I don't fully understand why it wasn't necessary to prepend an '*' to message in the printf call. I was under the assumption that message, since it is a pointer to a char, the first letter in the double quoted string, would display the address of the 'H'.
The %s format operator requires its corresponding argument to be a char * pointer. It prints the entire string that begins at that address. A string is a sequence of characters ending with a null byte. That's why this prints the entire message.
If you supply an array as the corresponding argument, it's automatically converted to a pointer to the first character of the array. In general, whenever an array is used as an r-value, it undergoes this conversion.
You don't need to use the * operator because the argument is supposed to be a pointer. If you used *message you would only pass the 'H' character to printf(). You would do this if you were using the %c format instead of %s -- its corresponding argument should be a char.
You're right that message is a pointer, of type "pointer to char", or char *. So if you were trying to print a character (an individual character), you would certainly have needed a *:
printf("first character: %c\n", *message);
In a printf format specifier, %c expects a character, which is what *message gives you.
But you weren't trying to print a single character, you were trying to print the whole string. And in a printf format specifier, %s expects a pointer to a character, the first of usually several characters to print. So
printf("entire string: %s\n", message);
is correct.
The conversion specifier %s is used to output strings (a sequence of characters terminated with the zero character '\0') pointers to first characters of which are passed to the function printf as an argument.
You can imagine that the function internally executes the following loop
for ( ; *message != '\0'; ++message )
{
printf( "%c", *message );
}
If you will supply the expression *message then it has type char and the function printf will try to interpret its value that is character 'H' as a value of a pointer. As result the function call will have undefined behavior.
To output the value of the pointer message you should use the conversion specifier %p like
printf( "%p", message );
Or as an integer value as for example
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
char *message = "Hello C Programmer!";
printf( "The value of the pointer message is %" PRIiPTR "\n", ( intptr_t )message );
return 0;
}
In addition, a pointer must be used here.
If you passed a character, it would be passed by value, and printf would lose the original address of the character. That means it would no longer be possible to access the characters that come after the first.
You need to pass a pointer by value to ensure you're retaining the original address of the head of the string.

why we need address operator to access two dimensional string elements

why we need address operator to access two dimensional string elements whereas in case of simple array we need not.we just use subscript notation in case of simple array
for ex
char masterlist[6][10] = {
"akshay",
"parag",
"raman",
"srinivas",
"gopal",
"rajesh"
};
printf("\nOriginal: %s %s", &names[2][0], &names[3][0] ) ;
whereas in case of array we just use
printf("%d",a[2][3]);
where a is an integer array.
The reason is simply because, when printf is invoked with %s as format specifier, it expects an argument of type char *, and not char which you would expect if you compare it to %d.
Format specifier %s is used to output strings - that is, sequences of characters - terminated with the null character '\0'.
If you have a two dimensional array with elements of type char, as in your example, then you can use the subscript operator:
char masterlist[6][10] = {
"akshay",
"parag",
"raman",
"srinivas",
"gopal",
"rajesh"
};
printf("\nOriginal: %s %s", names[2], names[3] ) ;
Both names[2] and names[3] have type char [10] and represent character strings.
If you want to compare with an integer array when the following statement is used:
printf("%d",a[2][3]);
Then it outputs an element of the array. You could write the same way for the original character array:
printf("%c", names[2][3] ) ;
This statement would output character 'a' (if I am not mistaken).
If you want to output an entire character string instead of a single element of the array you have to use code I showed above.
Consider a simplified example. Let's assume there is a function
void f( const char s[10] );
This function declaration is equivalent to
void f( const char *s );
and the both declare the same one function.
That is an array passed as an argument to the function will be adjusted to a pointer to its first element. If you have an array
char s[10] = "Hello";
then these expressions are equivalent
f( s );
f( &s[0] );
The both pass a pointer to the first element of the array.
In the second printf, you print a single int. In the first printf, you print a string, i.e. char array.
Because names[2][0] does not represent a string, it is a character from that string (in this case, the char p). &names[2][0] means "give me the address of the first character in that string", ie. the beginning of the string.
The language expects a pointer to a char as a string.
This is the way to print a string. In your 2-dimensional array you store strings. Even in the simple case where you had a string like char *string="Hello"; you would print it like this:
printf("%s", string); where string is a pointer. So when you want to print a string from an array you need to get the address of its first element.
To print out an array of characters (a string) you need to provide the function with the first value of the array (index 0).
Therefore you are saying &names[3][0], which basically returns the first element of the 4th array in the array names.
It's also equivalent to names[3] as they both point to the same place in the memory.

Resources