-1

I was learning C and i wanna to print a name using function, so i made this code:

#include <stdio.h>

void pn(char x);
void main()
{
    pn("HHH");

}
void pn(char x)
{
    printf("Hello %s\n",x);
}

and the output is nothing , so i change the argument and make it as pointer and then it works:

void pn(char* x);
void main()
{
    pn("HHH");

}
void pn(char* x)
{
    printf("Hello %s\n",x);
}

the output is : Hello HHH

as i know, pointer is to store address for a variable , but here i dont send any address ? so why it works only when i put a pointer as argument ?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Test065
  • 49
  • 6
  • 2
    Did you monitor the compiler warnings thrown in the first snippet? – Inian Jun 11 '20 at 16:43
  • 1
    `"HHH"` is a string literal, and in this case is an array of 4 chars. If you pass an array of char to a function that expects a single char, your compiler ought to warn you about the mismatch. If the compiler did not warn you, get a new compiler, or turn up the warnings. If the compiler did warn you and you chose to ignore the warning, proceed at your own risk. – William Pursell Jun 11 '20 at 17:03

3 Answers3

1

In the first program the function parameter

void pn(char x);

has the type char that is the function expects as an argument a single character.

However the function is called with the string literal "HHH" as its argument

pn("HHH");

String literals in C have types of character arrays. For example the string literal "HHH" has the type char[4] because the string literal includes also an invisible terminating zero character.

Used in expressions as for example as function arguments arrays are implicitly converted to pointers to their first elements. So the string literal "HHH" is converted to a temporary object of the type char * that points to the first character 'H'..

As a result the function has undefined behavior due to the incompatibility of the parameter and the corresponding argument.

In the second program the function parameter was correctly changed to the type char * and the program produced the expected result.

If you wanted to output just one character in the first program then it should be changed at least the following way

#include <stdio.h>

void pn(char x);
void main()
{
    pn("HHH"[0]);

}
void pn(char x)
{
    printf("Hello %c\n",x);
}

Or it would be more clear to call the function like

    pn( 'H' );

passing a character literal.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

A string in C is defined as an array of characters terminated with a null character. Arrays in C are defined by a pointer that points to the first element in the array.

Your function doesn't work because its parameter only accepts a single character as an argument, not a pointer to an array of characters.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
0

"So why it works only when I put a pointer as argument?"

"HHH" is a string literal of type array of 4 char (char [4]).

When you use a string literal as function argument in C, the string literal will be evaluated to a pointer to the first element of the char array consisting the string, type pointer to char (char *).

In this case, "HHH" will gain a pointer to the memory address of the first char element which contains the first H.

If you now use x as parameter of type char, there is:

  1. A type mismatch at calling the function pn between argument and parameter - char * vs. char, which invokes undefined behavior, and

  2. Also a type mismatch at printf("Hello %s\n",x); as the %s conversion specifier expects an argument of type pointer to char. This also invokes undefined behavior since you provided an argument of type char, which is not allowed per the C standard.

    "If a conversion specification is invalid, the behavior is undefined. 288) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."

    "288) See "future library directions" (7.31.11)."

    Source: C18, 7.21.6.1/9 - "The fprintf function"


Side notes:

  • Usually, a compiler should warn you about both type mismatches by default (without any additional flags). So you either seem to ignore the compiler warnings or don't got an appropriate compiler. Switch the compiler to GCC or Clang (if not done yet) and never ignore compiler warnings:

    Why should I always enable compiler warnings?