1

warning: it says to change %d for %I64d

char string[DIM]="hello";

printf("%d",strlen(string));
ryyker
  • 22,849
  • 3
  • 43
  • 87
Tenko
  • 123
  • 5
  • 2
    `strlen()` returns `size_t`, use `%zu` as format specifier. – David Ranieri Nov 30 '21 at 15:19
  • why it can not be read as %d if strlen outputs a number? – Tenko Nov 30 '21 at 15:19
  • @DavidRanieri when I change it for %zu it says the following warning: too many arguments for format – Tenko Nov 30 '21 at 15:20
  • 1
    If the _warning: too many arguments for format_, then check that the code you have here is the same as the actual code you are running on your computer. – ryyker Nov 30 '21 at 15:22
  • exactly the same, also it outputs this other warning warning: unknown conversion type character 'z' in format – Tenko Nov 30 '21 at 15:23
  • Please create a [mre] that you try to build and replicate yourself. Then copy-paste it in full into your question. – Some programmer dude Nov 30 '21 at 15:24
  • 1
    Also please tell us what compiler you're using, and which version of it. – Some programmer dude Nov 30 '21 at 15:24
  • 2
    are you using an old microsoft compiler? I remember around the VS2013 days `"%zu"` wasn't supported, think I had to use `"%Iu"`.. ? – yano Nov 30 '21 at 15:25
  • I am using mingw cc compiler. %Iu works fine, but the letter 'I' is colored in red but there is no warning and no error – Tenko Nov 30 '21 at 15:26
  • 3
    there's [this](https://stackoverflow.com/questions/44382862/how-to-printf-a-size-t-without-warning-in-mingw-w64-gcc-7-1) – yano Nov 30 '21 at 15:29
  • Yep see my answer in the above link by @yano. Tossing in `#define __USE_MINGW_ANSI_STDIO 1` before including stdio.h will fix the problem. This is caused by Mingw using Microsoft's C run-time which isn't conforming to the C language standard. – Lundin Nov 30 '21 at 15:33
  • Tenko, as able, try `"%zu"` and compile with version C11. – chux - Reinstate Monica Nov 30 '21 at 15:34
  • @chux-ReinstateMonica Won't matter, the issue is in the standard lib implementation. – Lundin Nov 30 '21 at 15:35
  • 3
    @Tenko There's a general theme here, in this as well as several of your other questions: *When calling `printf`, argument types **must** match their format specifiers, and doing so is **your** responsibility; the compiler will generally not insert any automatic conversions to match them up for you*. At best the compiler will warn you about mismatches. (Modern compilers do try to warn you, and are recommended for this reason.) – Steve Summit Nov 30 '21 at 15:46
  • @SteveSummit - your last comment addresses the issue better than any of the answers. – ryyker Nov 30 '21 at 15:51
  • @SteveSummit that is a really good awnser, it is the same for scanf? Or what happens with scanf? – Tenko Nov 30 '21 at 15:52
  • 1
    @Tenko It is the same for `scanf`, but it is also different for `scanf`. :-\ For `scanf`: (a) all arguments must be pointers, which means (b) you need `&` on most of them, except (c) not for `%s`, and also (d) you do have to be careful about `%f` versus `%lf` (unlike `printf`, where they're magically the same). And then `scanf` also has 17 other problems, but that's a story for another day. – Steve Summit Nov 30 '21 at 15:53
  • @SteveSummit perfect, but there is one thing that I don´t understand, why do I have to be carefull while I scanf a float or a double, If I scanf 1.34343 it could be a double or a float, why do I have to be careful with double or float in scanf then? – Tenko Nov 30 '21 at 15:56
  • Because for `printf` the [*default argument promotions*](https://stackoverflow.com/questions/1255775/default-argument-promotions-in-c-function-calls) apply, meaning `float` is promoted to `double`, so `printf` never sees a `float`, so `%f` expects a double, and the `l` in `%lf` is ignored. (Again, for `printf` only, *not* for `scanf`, where `%f` and `%lf` are definitely different!) This was explained in comments on Andreas Wenzel's answer. – Steve Summit Nov 30 '21 at 15:58
  • 1
    The default argument promotions don't affect pointers in any way. So for `scanf`, you have to get everything just right. If you do `scanf("%f", &d)`, where `d` is a `double`, it will probably only fill in half of the bits of `d`. And if you do `scanf("%lf", &f)`, where `f` is a `float`, it will probably overwrite memory outside of `f`. – Steve Summit Nov 30 '21 at 16:06
  • Ok, thanks everyone. Is it really imortant to mark the green tick of the best awnser? There are many awnsers that I think that have been helpful – Tenko Nov 30 '21 at 16:06
  • 1
    @Tenko Upvote the ones that were helpful, and it's always good to check the one you thought was best. (It can be hard to pick, I know.) – Steve Summit Nov 30 '21 at 16:07
  • Regarding `scanf` and the `%s` format, like it the `%[]` format arguments shouldn't use the pointer-to operator `&`. And like the `%c` format `%[]` doesn't skip leading space. – Some programmer dude Nov 30 '21 at 17:23

3 Answers3

4

As @AndreasWenzel answered "%zu" is the most most correct. But you wrote:

it outputs this warning when I put %zd warning: unknown conversion type character 'z' in format

if your implementation does not support "%z..." formats you need to convert the result of strlen to the largest possible unsigned integer.

printf( "%llu", (unsigned long long)strlen(string) );

But if your implementation does not support "%llu"

printf( "%lu", (unsigned long)strlen(string) );

And the last resort:

printf( "%u", (unsigned)strlen(string) );
ryyker
  • 22,849
  • 3
  • 43
  • 87
0___________
  • 60,014
  • 4
  • 34
  • 74
2

The %d printf format specifier expects an int. However, the return value of strlen is of type size_t.

The correct printf format specifier for size_t is %zu.

This line should work:

printf( "%zu", strlen(string) );
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • it outputs this warning when I put %zd warning: unknown conversion type character 'z' in format – Tenko Nov 30 '21 at 15:21
  • @Tenko: I have made a correction, please try again. – Andreas Wenzel Nov 30 '21 at 15:22
  • The same warning for %zu warning: unknown conversion type character 'z' in format – Tenko Nov 30 '21 at 15:22
  • 1
    Re "*unknown conversion type character 'z' in format*", It was added to the C standard 22 years ago in C99 – ikegami Nov 30 '21 at 15:23
  • 1
    @Tenko: Are you using Turbo C or some other very old compiler? – Andreas Wenzel Nov 30 '21 at 15:23
  • @ikegami I am imagining the OP is using mingw gcc, which is using MS libraries, which are catching up slowly. But I believe even these support `zu` in the recent versions – Eugene Sh. Nov 30 '21 at 15:24
  • @AndreasWenzel many library implementations do not support it – 0___________ Nov 30 '21 at 15:24
  • Yes I am using mingw gcc – Tenko Nov 30 '21 at 15:24
  • @Tenko, The warning is spurious. `%zu` is supported by the MS libraries used by mingw – ikegami Nov 30 '21 at 15:31
  • If int type is a number and size_t is a number also, why it can not be read as %d as a float can be read as a double or a double can be read as a float? – Tenko Nov 30 '21 at 15:39
  • @Tengo - It has to do with properly telling `printf()` the size and type of date it will be printing. `size_t` and `int` are two different types, with potentially two different sizes. It is undefined behavior to use a format specifier that does not match the data type being printed. – ryyker Nov 30 '21 at 15:40
  • 2
    @Tenko chocolate and ice cream are both sweets. But you would not be happy if you ask for the ice cream but the clerk will give you chocolate or mars bar instead. Same is with types. All are integral types, but they are diffrent – 0___________ Nov 30 '21 at 15:42
  • @0___________ so what happens when I put %f for a double?Why does it work? In your example float and double are differents and the float could be the chocolate and the double the ice cream – Tenko Nov 30 '21 at 15:43
  • @Tenko "%f" in printf is for double. `float` values or variables are always converted do double when used as `printf` parameters. So is not a good example. – 0___________ Nov 30 '21 at 15:45
  • 1
    @Tenko: The reason why you don't have to distinguish between `float` and `double` when using `printf` (in contrast to `scanf`) is that the `float` parameter [gets promoted](https://en.cppreference.com/w/c/language/conversion#Default_argument_promotions) to a `double`, because `printf` is a variadic function. However, `int` does not get promoted to `size_t`. – Andreas Wenzel Nov 30 '21 at 15:45
  • @AndreasWenzel good example, so %f is both bor float and double and %lf is also for both float and double? Why you said in contrastto scanf (id I scanf a value like 34.73637 it could be float or double right? – Tenko Nov 30 '21 at 15:49
  • @Tenko: Yes, with `printf`, there is no need to distinguish between `float` and `double`, because `float` gets promoted to `double`. Therefore, `%f` and `%lf` mean exactly the same thing with `printf`. But with `scanf`, you must still distinguish between `float` and `double` and there is a big difference between `%f` and `%lf`. That is because a `float *` does not get "promoted" to a `double *` (only `float` gets promoted to `double`) and `scanf` must know the size of the memory it is supposed to write to. – Andreas Wenzel Nov 30 '21 at 15:53
2

strlen doesn't return int. But your printf formats and their arguments must match. So just say

printf("%d", (int)strlen(string));

As long as your string is never longer than 32767 characters, you'll be fine.

The preferred solution is

printf("%zu", strlen(string));

but it sounds like your antique compiler doesn't support %zu. (You have my sympathies: I had a compiler at work for a long time that had the same problem.)

If you're worried about strings longer than 32767 characters, see the other answers, or this question: How can one print a size_t variable portably using the printf family?

Steve Summit
  • 45,437
  • 7
  • 70
  • 103