1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void fit(char *p , int n);
int main(void)
{
    char *mesg = "Hey, Lisa. You look so beautiful! "; // Line A
    puts(mesg);
    fit(mesg , 6);
    puts(mesg);
    system("pause");
    return 0;
}

void fit(char *p , int n)
{
    if(strlen(p) > n)
        *(p + n) = '\0';
}

Look at the code above. The function fit is designed to display only the first n characters of a string by putting a '\0' in position n+1. Here comes the problem. If in Line A, *mesg is replaced by mesg[], the program works fine. But *mesg doesn't function. I use vs2012. I know name in *name is a variable so name++ is OK while name in name[] is a constant so name++ isn't allowed. Apart from that difference, shouldn't *name and name[] be the same in declaring a string?

PPJack
  • 95
  • 1
  • 6
  • 5
    You can modify a character array, but you can't modify a string literal. See http://stackoverflow.com/q/1614723/10077 – Fred Larson Aug 23 '15 at 02:37
  • 4
    It is a historical legacy that does not require `char *mesg` to be `const char *mesg`, but it should be, Change to `const char *mesg` and the the compiler should error on `fit(mesg , 6);` – chux - Reinstate Monica Aug 23 '15 at 02:48

2 Answers2

3

In the C language, the following rules apply (some of them don't apply to others like C++):

  1. Arrays may degrade to pointers, possibly lossing their constant properties as described in rule 4.
  2. Any expression of the form x[y] is equivalent to *(x + y).
  3. A string literal represents a null-terminated array of characters.
  4. A variable name a for a given array is constant, and is equivalent to &a[0].
  5. For any non-constant, non-volatile type T, an expression of type T may be assigned to a variable name whose type may or not include the constant and/o volatile qualifiers, and if non-qualified would have type T, but an expression that constant and/or volatile qualified, and has type T when non-qualified, may not be assigned to a variable name that lacks the qualifiers of such an expression.

This implies that all the following assignments all valid:

  • char str[] = "Hello, world!\n", due to rule 3.
  • const char str[] = "Hello, world!\n", due to rules 3 and 5.
  • volatile char str[] = "Hello, world!\n", due to rules 3 and 5.
  • const volatile char str[] = "Hello, world!\n", due to rules 3 and 5.
  • char *str = "Hello, world!\n", due to rules 3 and 1.
  • const char *str = "Hello, world!\n", due to rules 3, 1, and 5.
  • volatile char *str = "Hello, world!\n", due to rules 3, 1, and 5.
  • const volatile char *str = "Hello, world!\n", due to rules 3, 1, and 5.

Given rules 4 and 5, a call to void fit(char*, int) shall fail if the expression assigned to the first argument is non-qualified, such as if given the statement const char *mesg = "Hey, Lisa. You look so beautiful!";, the variable name mesg is assigned to the first argument in a call to void fit(char*, int).

Just for completeness, rule 1 is strongered by rule 2, as seen in the expression *(p + n) = '\0' whenever p was degraded from an array at its assignment.

tl;dr: Most differences between both of the situations you described occur whenever a mismatch of qualifiers occur, as described in rule 5 above. This is mostly due to "historical reasons" (i.e: lazyness), and has affected other languages. For example, C++ saves some "compatibility with C", or in other words, compatibility with lazyness.

3442
  • 8,248
  • 2
  • 19
  • 41
3
char *mesg = "Hey, Lisa. You look so beautiful! "; // Line A

Here, this is string literal , thus a constant and you cannot modify its value.

What you can't do is -

mesg[0]='A';

And also what you have done in your code is wrong-

*(p + n) = '\0';   // equivalent to p[n]

mesg[]="Hey, Lisa. You look so beautiful! "; // would be same as your declaration if declared as const char mesg[]

In this declaration the expression is being used to initialize the contents another array, and is therefore not converted to a pointer type instead, the contents of the string literal are copied to mesg.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • Although if the OP had declared it as `char mesg[]`, all you said here would be incorrect in such a case... – 3442 Aug 23 '15 at 08:44
  • @KemyLand Please take a look. Yes I understand you point and I have made changes and thanks for your input :) – ameyCU Aug 23 '15 at 16:09
  • Yes, everything is now correct. Better edit than answer wrong :). – 3442 Aug 23 '15 at 20:42