简体   繁体   中英

What happens if you pass an int to a byte parameter in C?

How does C/C++ deal if you pass an int as a parameter into a method that takes in a byte (a char)? Does the int get truncated? Or something else?

For example:

void method1()
{
    int i = //some int;
    method2(i);
}

void method2(byte b)
{
     //Do something
}

How does the int get "cast" to a byte (a char)? Does it get truncated?

If byte stands for char type, the behavior will depend on whether char is signed or unsigned on your platform.

If char is unsigned, the original int value is reduced to the unsigned char range modulo UCHAR_MAX+1 . Values in [0, UCHAR_MAX] range are preserved. C language specification describes this process as

... the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

If char type is signed, then values within [SCHAR_MIN, SCHAR_MAX] range are preserved, while any values outside this range are converted in some implementation-defined way. (C language additionally explicitly allows an implementation-defined signal to be raised in such situations.) Ie there's no universal answer. Consult your platform's documentation. Or, better, write code that does not rely on any specific conversion behavior.

Just truncated AS bit pattern (byte is in general unsigned char, however, you have to check)

int i = -1;

becomes

byte b = 255; when byte = unsigned char

byte b = -1; when byte = signed char

i = 0; b = 0;

i = 1024; b = 0;

i = 1040; b = 16;

Quoting the C++ 2003 standard:

Clause 5.2.2 paragrah 4: When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument.

So, b is initialized with i . What does that mean?

8.5/14 the initial value of the object being initialized is the (possibly converted) value of the initializer expression. Standard conversions (clause 4) will be used, if necessary, to convert the initializer expression to the … destination type; no user-defined conversions are considered

Oh, i is converted , using the standard conversions . What does that mean? Among many other standard conversions are these:

4.7/2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2 n where n is the number of bits used to represent the unsigned type).

4.7/3 If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.

Oh, so if char is unsigned, the value is truncated to the number of bits in a char (or computed modulo UCHAR_MAX+1, whichever way you want to think about it.)

And if char is signed, then the value is unchanged, if it fits; implementation-defined otherwise.

In practice, on the computers and compilers you care about, the value is always truncated to fit in 8 bits, regardless of whether char s are signed or unsigned.

You don't tell what a byte is, but if you pass a parameter that is convertible to the parameter type, the value will be converted.

If the types have different value ranges there is a risk that the value is outside the range of the parameter type, and then it will not work. If it is within the range, it will be safe.

Here's an example:

1) Code:

#include <stdio.h>

void
method1 (unsigned char b)
{
  int a = 10;
  printf ("a=%d, b=%d...\n", a, b);
}

void
method2 (unsigned char * b)
{
  int a = 10;
  printf ("a=%d, b=%d...\n", a, *b);
}

int
main (int argc, char *argv[])
{
  int i=3;
  method1 (i);
  method2 (i);
  return 0;
}

2) Compile (with warning):

$ gcc -o x -Wall -pedantic x.c
x.c: In function `main':
x.c:22: warning: passing arg 1 of `method2' makes pointer from integer without a cast

3) Execute (with crash):

$ ./x
a=10, b=3...
Segmentation fault (core dumped)

'Hope that helps - both with your original question, and with related issues.

There are two cases to worry about:

// Your input "int i" gets truncated
void method2(byte b)
{
  ...

// Your "method2()" stack gets overwritten
void method2(byte * b)
{
  ...

It will be cast to a byte the same as if you casted it explicitly as (byte)i .

Your sample code above might be a different case though, unless you have a forward declaration for method2 that is not shown. Because method2 is not yet declared at the time it is called, the compiler doesn't know the type of its first parameter. In C, functions should be declared (or defined) before they are called. What happens in this case is that the compiler assumes (as an implicit declaration) that method2 's first parameter is an int and method2 receives an int . Officially that results in undefined behaviour, but on most architectures, both int and byte would be passed in the same size register anyway and it will happen to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM