1

Here's my code

#include <stdio.h>
#include <string.h>

int main(){
    char pal[8] = "ciaooaic";
    char pal1[7] = "ciaoaic";
    int lenPal = strlen(pal);
    int lenPal1 = strlen(pal1);
    printf("strlen('%s'): %d\n", pal, lenPal);
    printf("strlen('%s'): %d\n", pal1, lenPal1);
    return 0;
}

The problem is that when I run this code the output is:

strlen('ciaooaicP@'): 11
strlen('ciaoaic'): 7

The first string has also another non-printable char between P and @. I'm a noob, so maybe I missed something obvious. Can someone help me?

edit:

just give one extra space like char pal[9] = "ciaooaic"; char pal1[8] = "ciaoaic";

It works, but why? I understand that there should be a space for \0, but "ciaoaic" works without it...

  • just give one extra space like `char pal[9] = "ciaooaic"; char pal1[8] = "ciaoaic";` – Sina R. Nov 14 '15 at 10:38
  • 2
    Because due to undefined behaviour your code could give any output (_even correct output_) . – ameyCU Nov 14 '15 at 10:43
  • When you initialize strings, e.g. `char pal[] = "ciaooaic";` the compiler will include the null-terminator at the end (note: `'\0'` and `0` are equivalent). When you specify a size e.g. `pal[8]`, you limit the size of the array to just that size. If you happen to fill them all up with characters and leave no space for a null, the compiler is happy because it trusts you know what you meant. If by happenstance, the next character following `char pal[8] = "ciaooaic";` in memory is a `0`, then you accidentally have a null-terminates string. Don't count on that regularly happening... – David C. Rankin Nov 14 '15 at 10:58
  • Neither `pal` nor `pal1` is a string as defined by C11 §7.1.1 ¶1: _A string is a contiguous sequence of characters terminated by and including the first null character. The term multibyte string is sometimes used instead to emphasize special processing given to multibyte characters contained in the string or to avoid confusion with a wide string. A pointer to a string is a pointer to its initial (lowest addressed) character. The length of a string is the number of bytes preceding the null character and the value of a string is the sequence of the values of the contained characters, in order._ – Jonathan Leffler Feb 29 '20 at 15:00
  • See C11 [§6.7.9 Initialization ¶14](http://port70.net/~nsz/c/c11/n1570.html#6.7.9p14) for the verbiage that allows the non-string initialization: _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._ ¶2 is a constraint that states: _No initializer shall attempt to provide a value for an object not contained within the entity being initialized._ – Jonathan Leffler Feb 29 '20 at 15:26

3 Answers3

4

1. You don't leave room for a null terminator, as you pass them to strlen(), therefore your code exhibits undefined behaviour -

char pal[8] = "ciaooaic";
char pal1[7] = "ciaoaic";

Leave a space for '\0'. Declare and initialize like this -

char pal[9] = "ciaooaic";
char pal1[8] = "ciaoaic";

2. And strlen() returns size_t not int , so write like this -

size_t lenPal = strlen(pal);
size_t lenPal1 = strlen(pal1);

and use %zu specifier to print both these variables.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • `size_t` is just `unsigned int`, why are they different? – DMaster Nov 14 '15 at 10:46
  • 1
    @Dmaster: because an `unsigned int` is not an `int`. And `size_t` can also be an `unsigned long`. – Jongware Nov 14 '15 at 10:55
  • 2
    @DMaster That is implementation defined what it will be type of and there are other unsigned types also . – ameyCU Nov 14 '15 at 10:58
  • Even `size_t` is not `unsigned int`, but that doesn't cause the problem, we can even cast it to `short` and it still shows the same. Why mention it in the answer? – DMaster Nov 14 '15 at 15:13
  • 1
    @DMaster Point is that `strlen` returns `size_t` not `int` or `unsigned int` . That why I mentioned and I don't see any harm in it . And also , then it should be `unsigned int` specifically if you wan,t not `int` . – ameyCU Nov 14 '15 at 16:00
2

You have not kept space for the NULL terminating character \0.


Either increase the size of the array by 1

char pal[9] = "ciaooaic";
char pal1[8] = "ciaoaic";

OR

Do not specify the length at all

char pal[] = "ciaooaic";
char pal1[] = "ciaoaic";
Haris
  • 12,120
  • 6
  • 43
  • 70
0

Both the above answers are sufficient to solve your doubts. Increase the the length of both pal and pal1 by one as there there is no space for the assignment of the null character( '\0') at the end. However there is small trick to print the non null terminated character using printf

printf("strlen('%.*s'): %d\n",8, pal, lenPal);
printf("strlen('%.*s'): %d\n",7, pal1, lenPal1);

Link for the above trick:BRILLIANT

Community
  • 1
  • 1
Kalu
  • 290
  • 2
  • 13