-5

I'm not sure if I chose the right Title, but today I discovered (as a beginner in C) that for me strlen is not always the right decision to be made when I need it.

So I tried the following:

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

 int foo(char *s){
    int len = strlen(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    int len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%d)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%d)\n",c,len);
    }

    return 0;
}

Output:

False: C(10) > Len(5)

But when I compile with "-Wconversion" I get:

program.c:5:19: warning: conversion to ‘int’ from ‘size_t’ may alter its value [-Wconversion]
         int len = strlen(s);
                   ^

A quick fix will be to cast strlen:

int len = (int)strlen(s);

But I was not agree, so I decided that I really need something else, another approach maybe? I tried the following:

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

unsigned int size(char *s){
    unsigned int len;
    /* code here */
    len = (unsigned int)strlen(s);

    return len;
}

int main(void){
    char *name = "Michi";
    unsigned int len = size(name);
    int a = 20, b = 10, c = a - b;

    if(c < (signed int)len){
        printf("True:  C(%d) < Len(%d)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%d)\n",c,len);
    }

    return 0;
}

But I still need to cast strlen because of its return type (size_t which I know that is an unsigned type (typedef long unsigned int size_t;))

Finally I decided for another approach, to create my own function, which make things easier and with less possible future problems and I got:

#include<stdio.h>

long int stringLEN(char *s){
    int i = 0;
    long int len = 0;

    while (s[i] != '\0'){
        len++;
        i++;
    }

    return len;
 }

 long int foo(char *s){
    long int len = stringLEN(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    long int len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%ld)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%ld)\n",c,len);
    }

    return 0;
}

where no cast is needed anymore.

So my QUESTION is: is this (for my case) a better approach ? If not I need some explanations, my books (I have 3) does not explain me in that way that I can understand this things.

I know only that at some point cast could be a big problem, somehow.

EDIT: This code will also not compile with -Wconversion:

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

 size_t foo(char *s){
    size_t len = strlen(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    size_t len = foo(name);
    int a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%d) < Len(%zu)\n",c,len);
    }else{
        printf("False:  C(%d) > Len(%zu)\n",c,len);
    }

    return 0;
}

Output:

error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]|

But if I cast len works. I realized that, if the size is bigger then that int it will never fit.

Michi
  • 5,175
  • 7
  • 33
  • 58
  • 4
    what is the issue with `strlen()`? The problem is caused by how it is used, no? – Sourav Ghosh Sep 05 '15 at 20:06
  • strlen it defined as "typedef long unsigned int size_t;", so i have in my programs always problems when I compare an int (int a=10) with result from LEN (size_t len = strlen(string)). – Michi Sep 05 '15 at 20:08
  • 2
    This really has nothing to do with `strlen`. – juanchopanza Sep 05 '15 at 20:09
  • 1
    That's the point. Why you want to take the return value in an `int`, then? – Sourav Ghosh Sep 05 '15 at 20:09
  • 1
    @SouravGhosh Did you read my whole Post ? – Michi Sep 05 '15 at 20:11
  • 4
    Yes, I did, and I never found you used `size_t` anywhere. – Sourav Ghosh Sep 05 '15 at 20:12
  • Not me, but the strlen return it, i think you have no idea what i was asking, sorry. – Michi Sep 05 '15 at 20:13
  • 4
    Maybe if you asked a clear question it would be easier to understand. – juanchopanza Sep 05 '15 at 20:14
  • I already showed examples, what is not clear ? – Michi Sep 05 '15 at 20:16
  • 3
    As @SouravGhosh said you are not using `size_t`, why do you insist in using `int` to compare string length? Use `size_t` and you will not have any problems. – aghidini Sep 05 '15 at 20:16
  • 3
    What is your point? `clock` returns `clock_t`, `fopen` a `FILE *`, etc. This is the reason why there are different types. Use the correct type, cast where you **really** know what you are doing, otherwise you are in trouble. Note that `size_t` is not necessarily `unsigned long`. That is _implementation defined_ and exactly the reason `size_t` is used and not `unsigned long`. – too honest for this site Sep 05 '15 at 20:18
  • Is here somebody who can show me a code that compile with **"-Wconversion"** turned on, before you downvote me ? you just speak about standard , theories ...nothing more. show me a code like mine please. – Michi Sep 05 '15 at 20:22
  • You blamed me, now please show me a code that compiles. – Michi Sep 05 '15 at 20:24
  • 2
    In your first code example replace `int` with `size_t` **everywhere** and you'll be fine. – aghidini Sep 05 '15 at 20:25
  • @AndreaGhidini Sir, Why should i use size_t a , instead of int a ? Please explain. – Michi Sep 05 '15 at 20:27
  • @Olaf, Yes, and is not funny to make jokes on me, please. – Michi Sep 05 '15 at 20:27
  • 1
    @Michi: Why should you use `int` instead of `size_t`? Please explain! It is **you** complaining. – too honest for this site Sep 05 '15 at 20:27
  • @Olaf Why no one understand my point ? GCC complains on that – Michi Sep 05 '15 at 20:29
  • 1
    @Michi: I just do not understand what your problem is to use the correct type: `size_t`. You do not use `char` either. And the reason gcc complains has already been explained. Use `size_t` instead of `int` and be happy. If - for some reason - you need a signed type, you have to cast anyway, but first make sure you covered all bases. – too honest for this site Sep 05 '15 at 20:30
  • @Olaf how can i compare size_t len = strlen(string) with int a = 5. If i do a check like ....if(a – Michi Sep 05 '15 at 20:31
  • I do understand that is just a warning, but me I want to code, without warnings, that's all. Ich verstehe es nicht. – Michi Sep 05 '15 at 20:33
  • Thanks for reminding me, I just forgot. You still did not clarify what your problem, with `size_t` is. And, yes, I also have warnings enabled and my code does not generate any. – too honest for this site Sep 05 '15 at 20:33
  • @Olaf The problem is, that i get warnings and i tried to avoid them and I just asked if my last approach does that or not. But I got myself with a lot of downvote for such a question. – Michi Sep 05 '15 at 20:34
  • Your options are to use `size_t`, badly reinvent `strlen`, or use a cast to quiet the warning. You decide because you aren't taking the advice being offered. – Blastfurnace Sep 05 '15 at 20:37
  • @Michi we already told you how to avoid the warning (use `size_t`), if you don't like our advices it's your problem. – aghidini Sep 05 '15 at 20:37
  • @AndreaGhidini Sir, is not about that, I do undestand your point, but this make me to use everywhere size_t instead of int, when i have to compare something with size_t len = strlen(string). – Michi Sep 05 '15 at 20:39
  • @Michi correct, in fact you should strive to always use `size_t` instead of `int` for lengths comparisons. Why do you want to compare it with an `int`? – aghidini Sep 05 '15 at 20:40
  • @AndreaGhidini i showed you a peace of code, at some point I need to make that compare, please see again my examples where I use int a. – Michi Sep 05 '15 at 20:42
  • @Michi if for some reason (I cannot see it from your examples, just replace int...) you **must** compare a length with `int` you are out of luck because you are comparing different types and can lead to wrong results and a cast is inevitable. But, as the compiler warning says, you should not do that. – aghidini Sep 05 '15 at 20:45
  • @AndreaGhidini Sir, ok. Please try my last approach, i do not need a cast anymore. – Michi Sep 05 '15 at 20:46
  • 2
    @Michi: Just because you don't like your options doesn't change reality. Implement your own `strlen` and stop wasting other peoples' time. – Blastfurnace Sep 05 '15 at 20:49
  • @Blastfurnace Sir, did i just wast your time? Why did you joined here ? And about implementing my own one, I just did, there was the question too, was or was not a good approach. You keep downVoting my Question, feel free to do it. – Michi Sep 05 '15 at 20:51
  • 2
    @Michi your implementation of strlen will work for strings with a maximum length of INT_MAX and that is the same limit as the cast option. So the two solutions are equivalent, with your implementation you are simply hiding the problem under the carpet (and away from compiler eyes). – aghidini Sep 05 '15 at 20:53
  • @AndreaGhidini you mean **int** or **long int** My function returns **long int**, anyway thank you, you understand what was my point. – Michi Sep 05 '15 at 20:56
  • 1
    @Michi you can either not use **-Wconversion** or you can follow the advice given numerous times. Your question *"did I just really made a better approach?"* has a resounding answer NO! It's a bit soon to be replacing library functions. – Weather Vane Sep 05 '15 at 20:58
  • @WeatherVane I cannot give up on ** -Wconversion** because i'm new in c programming and i'm not so young Anymore. I learn this for Fun. It will be complicated for me. Thank you. – Michi Sep 05 '15 at 21:00
  • In POSIX-32 `int` and `long` have the same size. – too honest for this site Sep 05 '15 at 21:00
  • `long` is only guaranteed to have 32 bits as a minimum. – Weather Vane Sep 05 '15 at 21:01
  • @WeatherVane size_t is 64 ?, i do not know. please show me how can i find the range of size_t, for long int i use: printf("The minimum value of LONG = %ld\n", LONG_MIN); printf("The maximum value of LONG = %ld\n", LONG_MAX);, Which say : The minimum value of LONG = -9223372036854775808 The maximum value of LONG = 9223372036854775807 – Michi Sep 05 '15 at 21:12
  • 1
    `size_t` is implementation defined. – Weather Vane Sep 05 '15 at 21:16
  • 2
    @Michi: `limits.h`. Please do yourself (and us) a favour and read a good C book. "i'm new in c programming and i'm not so young Anymore" Being older is no excuse for ignorance. Do you really want to learn C or just get your own way, ignoring well meant advice from experienced C programmers (who might also not be that young anymore)? – too honest for this site Sep 05 '15 at 21:16
  • @Olaf, is the second time you recomand me a good book, i will read more, but i know one thing, you did not understand my point. Gute Nacht. – Michi Sep 05 '15 at 21:19
  • If you don't know it's size, you cant use a print formatting statement to tell you its range since you need to know it already. You could try `size_t a; printf("%zu", sizeof(a));` – Weather Vane Sep 05 '15 at 21:20
  • Which is 8 on my machine – Michi Sep 05 '15 at 21:21
  • So 64 bits, but your code might not work on another system, where it is 4. – Weather Vane Sep 05 '15 at 21:22
  • @WeatherVane i will try it on another Laptop which have 32bit. Thank you. – Michi Sep 05 '15 at 21:23
  • I have rewritten the question to reflect what the OP was trying to get at all along (as indicated by their having accepted my answer). – zwol Sep 05 '15 at 21:55
  • No, sorry, that was not my point. – Michi Sep 05 '15 at 21:55
  • 1
    @Michi If I didn't correctly understand your question, then why did you accept my answer? If I *did* correctly understand your question, what about the rewrite was wrong? – zwol Sep 05 '15 at 22:05

6 Answers6

6

Digging through all the other answers, your true question seems to be how to deal with a situation like this:

#include <string.h>
#include <libfoo.h>

extern void foo(void);
extern void bar(void);

void pick_foo_or_bar(const char *s)
{
   size_t slen = strlen(s);
   int   value = libfoo_api_returning_an_int();

   if (slen > value) // -Wconversion warning on this line
      foo();
   else
      bar();
}

... where you can't change the type of either slen or value, because both are correct for the API they're receiving the result of.

The -Wconversion warning is trying to tell you something meaningful. Comparison of signed and unsigned integer types in C does something very strange, not what you would expect from the laws of arithmetic in ; a naive comparison like what I wrote above can and has caused catastrophic bugs. But the cure is not casts or inventing your own strlen; the cure is to fix the comparison so it does what you expect from the laws of arithmetic. The principles for this are:

  • First check whether the signed quantity is negative. If so, treat it as smaller than the unsigned quantity.
  • Otherwise, cast the smaller type to the larger type before comparing them.

In this case, size_t is almost certain to be larger than, or the same size as, int, so you would write

#include <assert.h>
#include <limits.h>
#include <string.h>
#include <libfoo.h>

extern void foo(void);
extern void bar(void);

// Code below is correct only if size_t is at least as large as int.
static_assert(SIZE_MAX >= INT_MAX);

void pick_foo_or_bar(const char *s)
{
   size_t slen = strlen(s);
   int   value = libfoo_api_returning_an_int();

   if (value < 0 || (size_t)value < slen)
      foo();
   else
      bar();
}

The static_assert is present because, if I remember correctly, the C standard does not guarantee size_t being at least as large as unsigned int. I could, for instance, imagine an ABI for the 80286 where int was four bytes wide but size_t only two. In that situation you would need to do the casting the other way around:

void pick_foo_or_bar(unsigned short a, long b)
{
    if (b < 0 || b < (long)a)
        foo();
    else
        bar();
}

If you don't know which of the two types is bigger, or if you don't know which of them is signed, your only recourse in standard C is (u)intmax_t:

void pick_foo_or_bar(uid_t a, gid_t b)
{
    if (a < 0 && b < 0) {
        if ((intmax_t)a < (intmax_t)b)
            bar();
        else
            foo();
    } else if (a < 0) {
       bar();
    } else if (b < 0) {
        foo();
    } else {
        if ((uintmax_t)a < (uintmax_t)b)
            bar();
        else
            foo();
    }
 }

... and, given the exceedingly unfortunate precedent set by C99 wrt long, there probably will come a day when (u)intmax_t is not the biggest integer type supported by the compiler, and then you're just hosed.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • This is the best answer I got. Thank you. – Michi Sep 05 '15 at 21:35
  • Do not see the need in casting in `if ((intmax_t)a < (intmax_t)b)`. – chux - Reinstate Monica Sep 05 '15 at 21:58
  • 1
    @chux You're right in that if both are negative then they're both signed and the integer promotions will actually do the Right Thing. However, GCC 5 will still issue a `-Wsign-compare` warning without them. – zwol Sep 05 '15 at 22:01
  • We are speaking about char *name = "Michi";, what exactly means for you negative here ?? and we speak about int c = a-b(which is 10) , same here, where are those negative values ? – Michi Sep 05 '15 at 22:16
  • @Michi If there is a datum with a signed type that you cannot change, then you *must* assume that under some circumstances its value *can* be negative, even if you cannot persuade it to happen. – zwol Sep 05 '15 at 22:44
  • @zwol Thanks. BTW: the `pick_foo_or_bar()` is a good way to explain the general solution, but recommend something other than `time_t` as it has been known to be floating-point as allowed by C. – chux - Reinstate Monica Sep 05 '15 at 23:12
4

The lenght of a string can never be negative, whilst an integer could be - the warning is because the range of values for size_t is different to int, and some positive values of size_t would be treated as negative if cast to an int. The better option is to have the return type to your function match, in this case, have foo return a size_t - you'll soon see that the datatype would permiate most of the code, and leave some other oddities that could do odd things (size_t - size_t could underflow...)

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
  • As long as size_t returns unsigned you cannot compare it with an int, if you turn on compiler settings. – Michi Sep 05 '15 at 20:15
  • 1
    Correct. Which is why you'd need to change virtually all your `int`s to `size_t`. – Rowland Shaw Sep 05 '15 at 20:17
  • Exactly, using `int` to compare string length is wrong and could lead (albeit only for very long strings) to wrong results. – aghidini Sep 05 '15 at 20:18
  • Also note that signed `int` overflow is undefined behaviour. – juanchopanza Sep 05 '15 at 20:18
  • 3
    @Michi Compiler flags don't break your code. They tell you that your code was already broken. – juanchopanza Sep 05 '15 at 20:24
  • @RowlandShaw SIr, you right, but i cannot compare int a with size_t anymore, please read my post again. – Michi Sep 05 '15 at 20:25
  • 4
    @michi: what everyone is telling you is that you shouldn't be using `int` in the comparison. The fact that you really really want to use `int` doesn't make it correct. You're absolutely right that you should not compare `size_t` with `int` but the solution is not to make the `size_t` into an int, but rather to make the `int` into a `size_t` (but watch out for negative numbers). – rici Sep 05 '15 at 20:27
  • If at some point i need to compare and int with the result of strlen I get those warnings and i tried to avoid them, but not using cast. That's all. – Michi Sep 05 '15 at 20:37
  • 1
    @michi: I understand that. You need to either convert the unsigned type (size_t) to a signed type (int) -- which is undefined behaviour if it fails -- or you need to convert the signed type (int) to an unsigned type (size_t), which is never undefined behaviour but produces odd results if the value were negative. The one without undefined behaviour is better. – rici Sep 05 '15 at 20:39
  • @rici Sir, how is possible that you are the only one which understand my point ? – Michi Sep 05 '15 at 20:41
  • Unsigned integers cannot [overflow/underflow](http://port70.net/~nsz/c/c11/n1570.html#6.2.5p9). They wrap – too honest for this site Sep 05 '15 at 20:41
  • @rici: If the value of the unsigned can be represented in a signed integer, everything is well defined. UB only occurs if the value cannot be represented. So, if OP can assert the values are <= `INT_MAX`, there is not even a problem. – too honest for this site Sep 05 '15 at 20:43
  • @Olaf Sir, please stop, the whole thing was to avoid cast, in all examples i have to cast strlen to make it work, or declare **len** as size_t len, but then i need to cast all int's to can compile my programs. Please try to understand. – Michi Sep 05 '15 at 20:45
  • @Olaf: that's correct. And if the integer were not negative, the comparison wouldn't be problematic. If nothing causes a problem, there will be no problem, but that's not a good basis for defensive programming. – rici Sep 05 '15 at 20:46
  • 1
    @Michi what you are trying to do is wrong (comparing different datatypes) and you cannot avoid a warning, or a cast. – aghidini Sep 05 '15 at 20:46
  • @Michi: You can't have your cake and eat it too. (Wasch' mir den Pelz aber mach mich nicht nass). Perhaps you would be happier with a different language. Python has only one int-type with arbitrary range. – too honest for this site Sep 05 '15 at 20:46
  • @AndreaGhidini Is my last approach Wrong ? – Michi Sep 05 '15 at 20:47
  • @rici: I was talking about unsigned to signed conversion. For signed to unsigned, the behaviour is well-defined for all values (as long as all values can be represented by the unsigned, i.e. same bit-width). – too honest for this site Sep 05 '15 at 20:49
  • @olaf, that is precisely what i said a few comments ago. But the well-defined conversion of -1 to a very large size_t makes the comparison result unexpected, and that is why there is a compiler warning about comparisons in which that conversion could happen. Because they are usually bugs waiting to crash the shuttle. – rici Sep 05 '15 at 20:53
  • @rici: Normally you catch this either always, or with an assertion in the code. It is not **that** complicatted to add range-checking. I think, everything has been said twice at least here. OP just does not want to understand or accept and is fighting reality. – too honest for this site Sep 05 '15 at 20:56
2

This will compile without warnings:

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

 size_t foo(char *s){
    size_t len = strlen(s);
    /* code here */
    return len;
 }

int main(void){
    char *name = "Michi";
    size_t len = foo(name);
    size_t a = 20, b = 10, c = a - b;

    if(c < len){
        printf("True:  C(%zu) < Len(%zu)\n",c,len);
    } else {
        printf("False:  C(%zu) > Len(%zu)\n",c,len);
    }

    return 0;
}

as well explained in the answers and comments by @thomasdickey, @rolandshaw, @andreaghidini, @olaf, @juanchopanza and others.

Did you really made a better approach? No: why should a stringlen function return values that can be negative? There is no such thing as a string with negative size.

The standard strlen function is already there, is more efficient, is able to deal with strings with a maximum size which is twice the maximum size handled by stringLEN, and has a more precise definition of the return type.

Mario Zannone
  • 2,843
  • 12
  • 18
  • This force me to use size_t everywhere size_t a = 20, b = 10, c = a - b; I explained that i cannot use size_t, there will be int a at some point. Thank you anyway – Michi Sep 05 '15 at 21:05
  • Your answer should be, No, you need to always cast return of strlen if you need to compare it against int.That's all. Thank you again – Michi Sep 05 '15 at 21:06
  • @Michi: You did not explain why you need to compare against an int. Why do you need it? Sometimes a cast is inevitable, but in most cases a cast is a sign of some problem in the design of the solution. – Mario Zannone Sep 05 '15 at 21:12
  • Well, probably this is why no one understand me, but i have a big code (ever 500 lines) and at some point there is a check between the size of a string and a signal. That signal returns a length and strlen returns the length from that string, so i need to make a check if the signal's length is less then length. Hope you understand. Problem here is that, here are to many teachers with Theories. That's all. – Michi Sep 05 '15 at 21:16
  • Can you post a code sample including the signal? Maybe the problem is there. – Mario Zannone Sep 05 '15 at 21:25
  • Of course I can, but signal returns an int and at some point i need to compare if the return of signal (which is 100% not negative) is less then return from strlen. – Michi Sep 05 '15 at 21:39
  • Which signal are you talking about? The signal(3) function in stdlib does not return anything (it has a void return type). – Mario Zannone Sep 05 '15 at 21:52
  • No, sorry i speak about signal from some sensors. Anyway i gave out, i was treated with less respect. Please ignore my problem. – Michi Sep 05 '15 at 21:54
  • OK. In any case @zwol answer is excellent and I think closes the issue. – Mario Zannone Sep 05 '15 at 22:06
1

There are 2 issues:

  1. strlen() returns type size_t. size_t is some unsigned integer type likely as wide or wider than int. It is compiler/platform dependent.

  2. Code needs to compare and int to size_t. Since size_t is unsigned, and to prevent a warning of mixed signed/unsigned comparrison, explicitly change int to an unsigned integer. To change an non-negative int to an unsigned integer, cast to (unsigned).

To compare, test if c is negative and if not, then compare (unsigned)c directly to len. Compiler will covert types as needed and result in an arithmetically correct answer.

..

size_t len = strlen("SomeString");
int c = 20;  // some int

if (c < 0 || (unsigned)c < len) puts("c less than len");
else puts("c >= len");
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Is not working because i get "error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]|" – Michi Sep 05 '15 at 21:02
  • same thing "error: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Werror=sign-conversion]|" I use gcc version 4.9.2 – Michi Sep 05 '15 at 21:08
  • @Michi What is the lines and lines preceding the error? – chux - Reinstate Monica Sep 05 '15 at 21:13
  • if (c < 0 || c*1u < len) give me: "error: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Werror=sign-conversion]|" – Michi Sep 05 '15 at 21:26
  • Yes, if i cast it it will work, i know and a say it already. Thank you – Michi Sep 05 '15 at 21:28
  • @Michi I see, compiler is whining about the `int` to `unsigned` conversion in `c*1u`. Answer amended. – chux - Reinstate Monica Sep 05 '15 at 21:29
  • Yes, if i cast it it will work, i know and a say it already. Thank you – Michi Sep 05 '15 at 21:30
  • 1
    @Michi `int len = (int)strlen(s);` is a cast, but the wrong cast as it can easily truncate the length. A `(unsigned) c` is a problem when `c < -0`. By checking that `c` is non-negative and _then_ doing a `(unsigned) c` is the safe approach of this answer. – chux - Reinstate Monica Sep 05 '15 at 21:33
  • @Michi Another approach is `if (c*1LL < len*1LL)`. – chux - Reinstate Monica Sep 05 '15 at 21:35
  • same, "/home/michi/Templates/Programming/main.c|14|error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]|". Please use a GCC if you can. Anyway thank you for your explanation . – Michi Sep 05 '15 at 21:36
  • Answer does compile with gcc and no warning/error with [-Werror=sign-compare]. By casting `c` to `unsigned`, `static_assert(sizeof(size_t) >= sizeof(int));` is not needed. Code does _not_ need to cast the the smaller type to the larger type - that is guess-work in the general sense. All that is needed to to cast the signed type to its equivalent unsigned one. IMO, that is less guess work.) The compiler will extend the smaller of `(unsigned)c` or `len` as needed. – chux - Reinstate Monica Sep 05 '15 at 21:51
  • Your answer is 100% that it will be only one way. How can you predict that **int a** is smaller then **len**, or **int a** is greater than **len** ? – Michi Sep 05 '15 at 22:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/88897/discussion-between-chux-and-michi). – chux - Reinstate Monica Sep 05 '15 at 23:01
  • @Michi The answer works if `int a` is smaller or wider than `size_t len`. So no prediction is needed. – chux - Reinstate Monica Sep 05 '15 at 23:20
0

The normal way to solve this is to use variables typed size_t, and choose an appropriate format for printing them. Then no cast is needed. For printf, see these:

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • Is not working, you cannot compile if you compare the result with an int if you have gcc setting **"-Wconversion"** Turned On. – Michi Sep 05 '15 at 20:09
  • If you use `size_t` consistently, there will be no compiler warnings. – Thomas Dickey Sep 05 '15 at 20:11
  • You cannot compile if you try to compare int a with size_t len – Michi Sep 05 '15 at 20:12
  • Please show me a way that you can compile a program with **"-Wconversion"** . – Michi Sep 05 '15 at 20:18
  • Why should i print size_t ...where did you see that i use size_t in printf Function ? – Michi Sep 05 '15 at 20:20
  • Your program prints the result from foo, which ultimately (and consistently) gets its return value from strlen. For the record, I've been using that option about 20 years (see http://invisible-island.net/scripts/readme.html) – Thomas Dickey Sep 05 '15 at 20:24
-3

i think there must be varying from compiler to compiler.....because i tried it on a online compiler and it didn't show any warning.enter image description here

Oreo
  • 181
  • 1
  • 2
  • 12