How does casting really work for primitive data types? [closed]

Can a non-EU citizen travel within the Schengen area without identity documents?

Why is there a need to modify system call tables in linux?

Mother abusing my finances

Is the world in Game of Thrones spherical or flat?

Draw a checker pattern with a black X in the center

Team member doesn't give me the minimum time to complete a talk

Is there an explanation for Austria's Freedom Party virtually retaining its vote share despite recent scandal?

Can a wire having a 610-670 THz (frequency of blue light) AC frequency supply, generate blue light?

Did airlines fly their aircraft slower in response to oil prices in the 1970s?

Points within polygons in different projections

Is floating in space similar to falling under gravity?

How should I push back against my job assigning "homework"?

Why do Russians call their women expensive ("дорогая")?

My player wants to cast multiple charges of magic missile from a wand

Looking after a wayward brother in mother's will

Where can I find the list of all tendons in the human body?

How crucial is a waifu game storyline?

Could I be denied entry into Ireland due to medical and police situations during a previous UK visit?

If a massive object like Jupiter flew past the Earth how close would it need to come to pull people off of the surface?

How to prevent bad sectors?

What caused the tendency for conservatives to not support climate change regulations?

Different PCB color ( is it different material? )

How can I offer a test ride while selling a bike?

Can an old DSLR be upgraded to match modern smartphone image quality



How does casting really work for primitive data types? [closed]














1












$begingroup$


I have written the following C code which purpose it is to flip an unsigned number in binary representation and give back an unsigned number:



long flippingBits(long n) 
return (unsigned)(~n);


int main()
long a = flippingBits(someNumber);
...



This code does work fine. What about this code?



unsigned long flippingBits(long n) 
return (~n);


int main()
unsigned long a = flippingBits(someNumber);
...



This code indeed prints out negative numbers. WTF. This is beyond my intuition. So is there an (architectural) way, to explain this phenomenon? How does the casting of primitive data types work?










share|cite|improve this question











$endgroup$



closed as off-topic by David Richerby, xskxzr, chi, Evil, Gilles May 15 at 21:50


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Questions about software development or programming tools are off-topic here, but can be asked on Stack Overflow." – David Richerby, xskxzr, chi, Evil
If this question can be reworded to fit the rules in the help center, please edit the question.











  • 5




    $begingroup$
    This isn’t Computer Science, but very basic C programming. But since you are here, I’d advise you to google for “C Standard Draft” and use the document you find.
    $endgroup$
    – gnasher729
    May 15 at 15:09






  • 1




    $begingroup$
    There is no print command in the second example. What do you mean by "the code indeed prints out negative numbers"?
    $endgroup$
    – JiK
    May 15 at 19:24















1












$begingroup$


I have written the following C code which purpose it is to flip an unsigned number in binary representation and give back an unsigned number:



long flippingBits(long n) 
return (unsigned)(~n);


int main()
long a = flippingBits(someNumber);
...



This code does work fine. What about this code?



unsigned long flippingBits(long n) 
return (~n);


int main()
unsigned long a = flippingBits(someNumber);
...



This code indeed prints out negative numbers. WTF. This is beyond my intuition. So is there an (architectural) way, to explain this phenomenon? How does the casting of primitive data types work?










share|cite|improve this question











$endgroup$



closed as off-topic by David Richerby, xskxzr, chi, Evil, Gilles May 15 at 21:50


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Questions about software development or programming tools are off-topic here, but can be asked on Stack Overflow." – David Richerby, xskxzr, chi, Evil
If this question can be reworded to fit the rules in the help center, please edit the question.











  • 5




    $begingroup$
    This isn’t Computer Science, but very basic C programming. But since you are here, I’d advise you to google for “C Standard Draft” and use the document you find.
    $endgroup$
    – gnasher729
    May 15 at 15:09






  • 1




    $begingroup$
    There is no print command in the second example. What do you mean by "the code indeed prints out negative numbers"?
    $endgroup$
    – JiK
    May 15 at 19:24













1












1








1





$begingroup$


I have written the following C code which purpose it is to flip an unsigned number in binary representation and give back an unsigned number:



long flippingBits(long n) 
return (unsigned)(~n);


int main()
long a = flippingBits(someNumber);
...



This code does work fine. What about this code?



unsigned long flippingBits(long n) 
return (~n);


int main()
unsigned long a = flippingBits(someNumber);
...



This code indeed prints out negative numbers. WTF. This is beyond my intuition. So is there an (architectural) way, to explain this phenomenon? How does the casting of primitive data types work?










share|cite|improve this question











$endgroup$




I have written the following C code which purpose it is to flip an unsigned number in binary representation and give back an unsigned number:



long flippingBits(long n) 
return (unsigned)(~n);


int main()
long a = flippingBits(someNumber);
...



This code does work fine. What about this code?



unsigned long flippingBits(long n) 
return (~n);


int main()
unsigned long a = flippingBits(someNumber);
...



This code indeed prints out negative numbers. WTF. This is beyond my intuition. So is there an (architectural) way, to explain this phenomenon? How does the casting of primitive data types work?







c






share|cite|improve this question















share|cite|improve this question













share|cite|improve this question




share|cite|improve this question








edited May 15 at 21:50









Gilles

33.8k798166




33.8k798166










asked May 15 at 15:00









TVSuchtyTVSuchty

614




614




closed as off-topic by David Richerby, xskxzr, chi, Evil, Gilles May 15 at 21:50


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Questions about software development or programming tools are off-topic here, but can be asked on Stack Overflow." – David Richerby, xskxzr, chi, Evil
If this question can be reworded to fit the rules in the help center, please edit the question.







closed as off-topic by David Richerby, xskxzr, chi, Evil, Gilles May 15 at 21:50


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Questions about software development or programming tools are off-topic here, but can be asked on Stack Overflow." – David Richerby, xskxzr, chi, Evil
If this question can be reworded to fit the rules in the help center, please edit the question.







  • 5




    $begingroup$
    This isn’t Computer Science, but very basic C programming. But since you are here, I’d advise you to google for “C Standard Draft” and use the document you find.
    $endgroup$
    – gnasher729
    May 15 at 15:09






  • 1




    $begingroup$
    There is no print command in the second example. What do you mean by "the code indeed prints out negative numbers"?
    $endgroup$
    – JiK
    May 15 at 19:24












  • 5




    $begingroup$
    This isn’t Computer Science, but very basic C programming. But since you are here, I’d advise you to google for “C Standard Draft” and use the document you find.
    $endgroup$
    – gnasher729
    May 15 at 15:09






  • 1




    $begingroup$
    There is no print command in the second example. What do you mean by "the code indeed prints out negative numbers"?
    $endgroup$
    – JiK
    May 15 at 19:24







5




5




$begingroup$
This isn’t Computer Science, but very basic C programming. But since you are here, I’d advise you to google for “C Standard Draft” and use the document you find.
$endgroup$
– gnasher729
May 15 at 15:09




$begingroup$
This isn’t Computer Science, but very basic C programming. But since you are here, I’d advise you to google for “C Standard Draft” and use the document you find.
$endgroup$
– gnasher729
May 15 at 15:09




1




1




$begingroup$
There is no print command in the second example. What do you mean by "the code indeed prints out negative numbers"?
$endgroup$
– JiK
May 15 at 19:24




$begingroup$
There is no print command in the second example. What do you mean by "the code indeed prints out negative numbers"?
$endgroup$
– JiK
May 15 at 19:24










2 Answers
2






active

oldest

votes


















2












$begingroup$

Casting of primitive datatypes works in a very simple way:




Under the hood, values don't have types. Casting does absolutely nothing.




As a simple example, let us consider casting 65 to an ASCII character, thus obtaining the symbol A. What happens under the hood? Absolutely nothing. The only thing that changes is how the program treats the value. When it thinks of it as an integer, it sees 65; when it thinks of it as an ASCII character it sees A.



The CPU does accommodate different datatypes when performing various operations. For example, it has separate instructions for signed and unsigned integer arithmetic, and for floating point arithmetic. Moreover, there are different instruction for different lengths (i.e. 16-bit vs. 32-bit vs. 64-bit for integers). But it is up to the programmer to instruct the CPU which instruction to use. The CPU doesn't keep track of datatypes, which are a higher-level concept.



Modern CPUs do keep a distinction between code and data to some extent, for security purposes. But otherwise the semantics of data is up to the programmer.



Sometimes casting does have an actual effect, and this is during promotion. When casting an integer to a floating point number, or a 32-bit integer to a 64-bit integer, the program calls some instruction which effects this conversion (in the second case, the exact instruction depends on whether the integer is signed or unsigned).



When casting a signed integer to an unsigned integer of the same length (or vice versa), probably nothing happens. This is exactly your case.






share|cite|improve this answer











$endgroup$








  • 3




    $begingroup$
    "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
    $endgroup$
    – user2357112
    May 15 at 19:02






  • 1




    $begingroup$
    (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
    $endgroup$
    – user2357112
    May 15 at 19:02










  • $begingroup$
    The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
    $endgroup$
    – Yuval Filmus
    May 15 at 19:03






  • 1




    $begingroup$
    Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
    $endgroup$
    – Gilles
    May 15 at 21:58






  • 1




    $begingroup$
    (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
    $endgroup$
    – Gilles
    May 15 at 22:00


















1












$begingroup$


How does the casting of primitive datatypes works?




The restriction "primitive datatype" is not enough:



Casting from a 16-bit integer to a 32-bit integer works differently than casting between integer types of the same size. And casting between integer and floating-point types is even more complex.




This Code does work fine. What about this code?




Both code examples will work differently on different CPUs, operating systems and possibly using different compilers.



This is because under some operating systems (e.g. 32-bit Windows) long and unsigned data types have the same number of bits; under other operating systems (e.g. 64-bit Windows) long has twice as many bits as unsigned.



And you use the ~ operator (~n) on a signed data type which may cause different results depending on the compiler you use.




This code indeed prints out negative numbers.



So is there an (architectural) way, to explain this phenomenon?




There are two effects:



The first effect is:



If you pass a value of a wrong data type to some function, C will automatically cast the value.



And if you are casting a value that is outside the range of the data type you are casting to, the result will typically not be what you are intuitively expecting.



In the case of two integer data types, normally the "rightmost" bits of the value are copied to the new value.



Let's take (signed char)3478 as an example:



The number 3478 is written as 110110010110 in binary. signed char is an 8 bit data type. The rightmost 8 bits of 1101 10010110 are 10010110. And the value (-106) is stored as 10010110 in a signed char variable.



Therefore (signed char)3478 will result in (-106).



The value a is stored in an unsigned long variable which means that it cannot be negative!



However, you say that you "print out" the value of a. This means you pass the value to some function that prints it to the screen.



Obviously that function expects some signed data type. C will cast the value stored in a to the signed data type and as in the example with the number 3478, the result of casting may be a negative number.



If you use printf you may see a second effect:



If some function (such as printf) has a variable number of parameters, the way the parameters are passed to the function is depending on the data types passed. (The details may also vary from OS to OS.)



You may now pass the wrong data type to the function; for example you use "%d" (signed int) in the printf format string but you pass an unsigned long.



If you do this, the compiler will write the value of a to some data storage (memory or register) which is suitable for unsigned long values before actually calling the function. (For such functions the compiler is not able to find out which data type is really expected by the function, so it has to assume that the function expects the data type you are passing to the function.)



However, printf will look for a value in some data storage suitable for signed int values which might be located somewhere completely different. That data storage does not contain any useful value because the compiler wrote the value of a somewhere else!






share|cite|improve this answer











$endgroup$



















    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2












    $begingroup$

    Casting of primitive datatypes works in a very simple way:




    Under the hood, values don't have types. Casting does absolutely nothing.




    As a simple example, let us consider casting 65 to an ASCII character, thus obtaining the symbol A. What happens under the hood? Absolutely nothing. The only thing that changes is how the program treats the value. When it thinks of it as an integer, it sees 65; when it thinks of it as an ASCII character it sees A.



    The CPU does accommodate different datatypes when performing various operations. For example, it has separate instructions for signed and unsigned integer arithmetic, and for floating point arithmetic. Moreover, there are different instruction for different lengths (i.e. 16-bit vs. 32-bit vs. 64-bit for integers). But it is up to the programmer to instruct the CPU which instruction to use. The CPU doesn't keep track of datatypes, which are a higher-level concept.



    Modern CPUs do keep a distinction between code and data to some extent, for security purposes. But otherwise the semantics of data is up to the programmer.



    Sometimes casting does have an actual effect, and this is during promotion. When casting an integer to a floating point number, or a 32-bit integer to a 64-bit integer, the program calls some instruction which effects this conversion (in the second case, the exact instruction depends on whether the integer is signed or unsigned).



    When casting a signed integer to an unsigned integer of the same length (or vice versa), probably nothing happens. This is exactly your case.






    share|cite|improve this answer











    $endgroup$








    • 3




      $begingroup$
      "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
      $endgroup$
      – user2357112
      May 15 at 19:02






    • 1




      $begingroup$
      (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
      $endgroup$
      – user2357112
      May 15 at 19:02










    • $begingroup$
      The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
      $endgroup$
      – Yuval Filmus
      May 15 at 19:03






    • 1




      $begingroup$
      Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
      $endgroup$
      – Gilles
      May 15 at 21:58






    • 1




      $begingroup$
      (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
      $endgroup$
      – Gilles
      May 15 at 22:00















    2












    $begingroup$

    Casting of primitive datatypes works in a very simple way:




    Under the hood, values don't have types. Casting does absolutely nothing.




    As a simple example, let us consider casting 65 to an ASCII character, thus obtaining the symbol A. What happens under the hood? Absolutely nothing. The only thing that changes is how the program treats the value. When it thinks of it as an integer, it sees 65; when it thinks of it as an ASCII character it sees A.



    The CPU does accommodate different datatypes when performing various operations. For example, it has separate instructions for signed and unsigned integer arithmetic, and for floating point arithmetic. Moreover, there are different instruction for different lengths (i.e. 16-bit vs. 32-bit vs. 64-bit for integers). But it is up to the programmer to instruct the CPU which instruction to use. The CPU doesn't keep track of datatypes, which are a higher-level concept.



    Modern CPUs do keep a distinction between code and data to some extent, for security purposes. But otherwise the semantics of data is up to the programmer.



    Sometimes casting does have an actual effect, and this is during promotion. When casting an integer to a floating point number, or a 32-bit integer to a 64-bit integer, the program calls some instruction which effects this conversion (in the second case, the exact instruction depends on whether the integer is signed or unsigned).



    When casting a signed integer to an unsigned integer of the same length (or vice versa), probably nothing happens. This is exactly your case.






    share|cite|improve this answer











    $endgroup$








    • 3




      $begingroup$
      "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
      $endgroup$
      – user2357112
      May 15 at 19:02






    • 1




      $begingroup$
      (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
      $endgroup$
      – user2357112
      May 15 at 19:02










    • $begingroup$
      The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
      $endgroup$
      – Yuval Filmus
      May 15 at 19:03






    • 1




      $begingroup$
      Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
      $endgroup$
      – Gilles
      May 15 at 21:58






    • 1




      $begingroup$
      (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
      $endgroup$
      – Gilles
      May 15 at 22:00













    2












    2








    2





    $begingroup$

    Casting of primitive datatypes works in a very simple way:




    Under the hood, values don't have types. Casting does absolutely nothing.




    As a simple example, let us consider casting 65 to an ASCII character, thus obtaining the symbol A. What happens under the hood? Absolutely nothing. The only thing that changes is how the program treats the value. When it thinks of it as an integer, it sees 65; when it thinks of it as an ASCII character it sees A.



    The CPU does accommodate different datatypes when performing various operations. For example, it has separate instructions for signed and unsigned integer arithmetic, and for floating point arithmetic. Moreover, there are different instruction for different lengths (i.e. 16-bit vs. 32-bit vs. 64-bit for integers). But it is up to the programmer to instruct the CPU which instruction to use. The CPU doesn't keep track of datatypes, which are a higher-level concept.



    Modern CPUs do keep a distinction between code and data to some extent, for security purposes. But otherwise the semantics of data is up to the programmer.



    Sometimes casting does have an actual effect, and this is during promotion. When casting an integer to a floating point number, or a 32-bit integer to a 64-bit integer, the program calls some instruction which effects this conversion (in the second case, the exact instruction depends on whether the integer is signed or unsigned).



    When casting a signed integer to an unsigned integer of the same length (or vice versa), probably nothing happens. This is exactly your case.






    share|cite|improve this answer











    $endgroup$



    Casting of primitive datatypes works in a very simple way:




    Under the hood, values don't have types. Casting does absolutely nothing.




    As a simple example, let us consider casting 65 to an ASCII character, thus obtaining the symbol A. What happens under the hood? Absolutely nothing. The only thing that changes is how the program treats the value. When it thinks of it as an integer, it sees 65; when it thinks of it as an ASCII character it sees A.



    The CPU does accommodate different datatypes when performing various operations. For example, it has separate instructions for signed and unsigned integer arithmetic, and for floating point arithmetic. Moreover, there are different instruction for different lengths (i.e. 16-bit vs. 32-bit vs. 64-bit for integers). But it is up to the programmer to instruct the CPU which instruction to use. The CPU doesn't keep track of datatypes, which are a higher-level concept.



    Modern CPUs do keep a distinction between code and data to some extent, for security purposes. But otherwise the semantics of data is up to the programmer.



    Sometimes casting does have an actual effect, and this is during promotion. When casting an integer to a floating point number, or a 32-bit integer to a 64-bit integer, the program calls some instruction which effects this conversion (in the second case, the exact instruction depends on whether the integer is signed or unsigned).



    When casting a signed integer to an unsigned integer of the same length (or vice versa), probably nothing happens. This is exactly your case.







    share|cite|improve this answer














    share|cite|improve this answer



    share|cite|improve this answer








    edited May 15 at 21:41









    z3p5e6

    31




    31










    answered May 15 at 15:23









    Yuval FilmusYuval Filmus

    200k15194358




    200k15194358







    • 3




      $begingroup$
      "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
      $endgroup$
      – user2357112
      May 15 at 19:02






    • 1




      $begingroup$
      (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
      $endgroup$
      – user2357112
      May 15 at 19:02










    • $begingroup$
      The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
      $endgroup$
      – Yuval Filmus
      May 15 at 19:03






    • 1




      $begingroup$
      Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
      $endgroup$
      – Gilles
      May 15 at 21:58






    • 1




      $begingroup$
      (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
      $endgroup$
      – Gilles
      May 15 at 22:00












    • 3




      $begingroup$
      "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
      $endgroup$
      – user2357112
      May 15 at 19:02






    • 1




      $begingroup$
      (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
      $endgroup$
      – user2357112
      May 15 at 19:02










    • $begingroup$
      The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
      $endgroup$
      – Yuval Filmus
      May 15 at 19:03






    • 1




      $begingroup$
      Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
      $endgroup$
      – Gilles
      May 15 at 21:58






    • 1




      $begingroup$
      (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
      $endgroup$
      – Gilles
      May 15 at 22:00







    3




    3




    $begingroup$
    "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
    $endgroup$
    – user2357112
    May 15 at 19:02




    $begingroup$
    "Casting does absolutely nothing" is too broad a statement to lead with. It only does nothing for this particular cast, and only because of the signed and unsigned integer representations we've chosen. Especially for integer->floating or floating->integer casts, the new and old bit patterns in memory could be completely different. If offset binary had somehow become the standard for signed integers, unsigned->signed and signed->unsigned would change the bit pattern too.
    $endgroup$
    – user2357112
    May 15 at 19:02




    1




    1




    $begingroup$
    (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
    $endgroup$
    – user2357112
    May 15 at 19:02




    $begingroup$
    (We don't have to worry about offset binary in our timeline, and it's forbidden by the C standard, but if things had played out differently, we could have had to deal with integer formats where the signed and unsigned representations of the same nonnegative number don't match.)
    $endgroup$
    – user2357112
    May 15 at 19:02












    $begingroup$
    The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
    $endgroup$
    – Yuval Filmus
    May 15 at 19:03




    $begingroup$
    The main point is that datatypes are an artificial construct. Down below it's just bits. Only the program can give them meaning.
    $endgroup$
    – Yuval Filmus
    May 15 at 19:03




    1




    1




    $begingroup$
    Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
    $endgroup$
    – Gilles
    May 15 at 21:58




    $begingroup$
    Plenty of things are misleading or inaccurate in this answer. You're describing a sort of idealized 1970s C on a typical byte-oriented machine, but modern compilers have optimizations that make the semantics of practical-C a lot more subtle, while remaining compliant with the semantics defined by the C standard. “Casting does absolutely nothing” is wrong by any perspective. Between integer types of different ranges, it can apply a modulo operation (or sometimes other effects). When floating point is involved, it can approximate.
    $endgroup$
    – Gilles
    May 15 at 21:58




    1




    1




    $begingroup$
    (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
    $endgroup$
    – Gilles
    May 15 at 22:00




    $begingroup$
    (cont.) Promotion is a technical term for certain automatic conversions. (A conversion is basically an implicit cast, and a cast is basically an explicit conversion.) There is no casting between 'A' and 65: both are literals of type int. When casting a signed integer to an unsigned integer, the value and (on virtually all implementations) the bit pattern are preserved only if the value is non-negative.
    $endgroup$
    – Gilles
    May 15 at 22:00











    1












    $begingroup$


    How does the casting of primitive datatypes works?




    The restriction "primitive datatype" is not enough:



    Casting from a 16-bit integer to a 32-bit integer works differently than casting between integer types of the same size. And casting between integer and floating-point types is even more complex.




    This Code does work fine. What about this code?




    Both code examples will work differently on different CPUs, operating systems and possibly using different compilers.



    This is because under some operating systems (e.g. 32-bit Windows) long and unsigned data types have the same number of bits; under other operating systems (e.g. 64-bit Windows) long has twice as many bits as unsigned.



    And you use the ~ operator (~n) on a signed data type which may cause different results depending on the compiler you use.




    This code indeed prints out negative numbers.



    So is there an (architectural) way, to explain this phenomenon?




    There are two effects:



    The first effect is:



    If you pass a value of a wrong data type to some function, C will automatically cast the value.



    And if you are casting a value that is outside the range of the data type you are casting to, the result will typically not be what you are intuitively expecting.



    In the case of two integer data types, normally the "rightmost" bits of the value are copied to the new value.



    Let's take (signed char)3478 as an example:



    The number 3478 is written as 110110010110 in binary. signed char is an 8 bit data type. The rightmost 8 bits of 1101 10010110 are 10010110. And the value (-106) is stored as 10010110 in a signed char variable.



    Therefore (signed char)3478 will result in (-106).



    The value a is stored in an unsigned long variable which means that it cannot be negative!



    However, you say that you "print out" the value of a. This means you pass the value to some function that prints it to the screen.



    Obviously that function expects some signed data type. C will cast the value stored in a to the signed data type and as in the example with the number 3478, the result of casting may be a negative number.



    If you use printf you may see a second effect:



    If some function (such as printf) has a variable number of parameters, the way the parameters are passed to the function is depending on the data types passed. (The details may also vary from OS to OS.)



    You may now pass the wrong data type to the function; for example you use "%d" (signed int) in the printf format string but you pass an unsigned long.



    If you do this, the compiler will write the value of a to some data storage (memory or register) which is suitable for unsigned long values before actually calling the function. (For such functions the compiler is not able to find out which data type is really expected by the function, so it has to assume that the function expects the data type you are passing to the function.)



    However, printf will look for a value in some data storage suitable for signed int values which might be located somewhere completely different. That data storage does not contain any useful value because the compiler wrote the value of a somewhere else!






    share|cite|improve this answer











    $endgroup$

















      1












      $begingroup$


      How does the casting of primitive datatypes works?




      The restriction "primitive datatype" is not enough:



      Casting from a 16-bit integer to a 32-bit integer works differently than casting between integer types of the same size. And casting between integer and floating-point types is even more complex.




      This Code does work fine. What about this code?




      Both code examples will work differently on different CPUs, operating systems and possibly using different compilers.



      This is because under some operating systems (e.g. 32-bit Windows) long and unsigned data types have the same number of bits; under other operating systems (e.g. 64-bit Windows) long has twice as many bits as unsigned.



      And you use the ~ operator (~n) on a signed data type which may cause different results depending on the compiler you use.




      This code indeed prints out negative numbers.



      So is there an (architectural) way, to explain this phenomenon?




      There are two effects:



      The first effect is:



      If you pass a value of a wrong data type to some function, C will automatically cast the value.



      And if you are casting a value that is outside the range of the data type you are casting to, the result will typically not be what you are intuitively expecting.



      In the case of two integer data types, normally the "rightmost" bits of the value are copied to the new value.



      Let's take (signed char)3478 as an example:



      The number 3478 is written as 110110010110 in binary. signed char is an 8 bit data type. The rightmost 8 bits of 1101 10010110 are 10010110. And the value (-106) is stored as 10010110 in a signed char variable.



      Therefore (signed char)3478 will result in (-106).



      The value a is stored in an unsigned long variable which means that it cannot be negative!



      However, you say that you "print out" the value of a. This means you pass the value to some function that prints it to the screen.



      Obviously that function expects some signed data type. C will cast the value stored in a to the signed data type and as in the example with the number 3478, the result of casting may be a negative number.



      If you use printf you may see a second effect:



      If some function (such as printf) has a variable number of parameters, the way the parameters are passed to the function is depending on the data types passed. (The details may also vary from OS to OS.)



      You may now pass the wrong data type to the function; for example you use "%d" (signed int) in the printf format string but you pass an unsigned long.



      If you do this, the compiler will write the value of a to some data storage (memory or register) which is suitable for unsigned long values before actually calling the function. (For such functions the compiler is not able to find out which data type is really expected by the function, so it has to assume that the function expects the data type you are passing to the function.)



      However, printf will look for a value in some data storage suitable for signed int values which might be located somewhere completely different. That data storage does not contain any useful value because the compiler wrote the value of a somewhere else!






      share|cite|improve this answer











      $endgroup$















        1












        1








        1





        $begingroup$


        How does the casting of primitive datatypes works?




        The restriction "primitive datatype" is not enough:



        Casting from a 16-bit integer to a 32-bit integer works differently than casting between integer types of the same size. And casting between integer and floating-point types is even more complex.




        This Code does work fine. What about this code?




        Both code examples will work differently on different CPUs, operating systems and possibly using different compilers.



        This is because under some operating systems (e.g. 32-bit Windows) long and unsigned data types have the same number of bits; under other operating systems (e.g. 64-bit Windows) long has twice as many bits as unsigned.



        And you use the ~ operator (~n) on a signed data type which may cause different results depending on the compiler you use.




        This code indeed prints out negative numbers.



        So is there an (architectural) way, to explain this phenomenon?




        There are two effects:



        The first effect is:



        If you pass a value of a wrong data type to some function, C will automatically cast the value.



        And if you are casting a value that is outside the range of the data type you are casting to, the result will typically not be what you are intuitively expecting.



        In the case of two integer data types, normally the "rightmost" bits of the value are copied to the new value.



        Let's take (signed char)3478 as an example:



        The number 3478 is written as 110110010110 in binary. signed char is an 8 bit data type. The rightmost 8 bits of 1101 10010110 are 10010110. And the value (-106) is stored as 10010110 in a signed char variable.



        Therefore (signed char)3478 will result in (-106).



        The value a is stored in an unsigned long variable which means that it cannot be negative!



        However, you say that you "print out" the value of a. This means you pass the value to some function that prints it to the screen.



        Obviously that function expects some signed data type. C will cast the value stored in a to the signed data type and as in the example with the number 3478, the result of casting may be a negative number.



        If you use printf you may see a second effect:



        If some function (such as printf) has a variable number of parameters, the way the parameters are passed to the function is depending on the data types passed. (The details may also vary from OS to OS.)



        You may now pass the wrong data type to the function; for example you use "%d" (signed int) in the printf format string but you pass an unsigned long.



        If you do this, the compiler will write the value of a to some data storage (memory or register) which is suitable for unsigned long values before actually calling the function. (For such functions the compiler is not able to find out which data type is really expected by the function, so it has to assume that the function expects the data type you are passing to the function.)



        However, printf will look for a value in some data storage suitable for signed int values which might be located somewhere completely different. That data storage does not contain any useful value because the compiler wrote the value of a somewhere else!






        share|cite|improve this answer











        $endgroup$




        How does the casting of primitive datatypes works?




        The restriction "primitive datatype" is not enough:



        Casting from a 16-bit integer to a 32-bit integer works differently than casting between integer types of the same size. And casting between integer and floating-point types is even more complex.




        This Code does work fine. What about this code?




        Both code examples will work differently on different CPUs, operating systems and possibly using different compilers.



        This is because under some operating systems (e.g. 32-bit Windows) long and unsigned data types have the same number of bits; under other operating systems (e.g. 64-bit Windows) long has twice as many bits as unsigned.



        And you use the ~ operator (~n) on a signed data type which may cause different results depending on the compiler you use.




        This code indeed prints out negative numbers.



        So is there an (architectural) way, to explain this phenomenon?




        There are two effects:



        The first effect is:



        If you pass a value of a wrong data type to some function, C will automatically cast the value.



        And if you are casting a value that is outside the range of the data type you are casting to, the result will typically not be what you are intuitively expecting.



        In the case of two integer data types, normally the "rightmost" bits of the value are copied to the new value.



        Let's take (signed char)3478 as an example:



        The number 3478 is written as 110110010110 in binary. signed char is an 8 bit data type. The rightmost 8 bits of 1101 10010110 are 10010110. And the value (-106) is stored as 10010110 in a signed char variable.



        Therefore (signed char)3478 will result in (-106).



        The value a is stored in an unsigned long variable which means that it cannot be negative!



        However, you say that you "print out" the value of a. This means you pass the value to some function that prints it to the screen.



        Obviously that function expects some signed data type. C will cast the value stored in a to the signed data type and as in the example with the number 3478, the result of casting may be a negative number.



        If you use printf you may see a second effect:



        If some function (such as printf) has a variable number of parameters, the way the parameters are passed to the function is depending on the data types passed. (The details may also vary from OS to OS.)



        You may now pass the wrong data type to the function; for example you use "%d" (signed int) in the printf format string but you pass an unsigned long.



        If you do this, the compiler will write the value of a to some data storage (memory or register) which is suitable for unsigned long values before actually calling the function. (For such functions the compiler is not able to find out which data type is really expected by the function, so it has to assume that the function expects the data type you are passing to the function.)



        However, printf will look for a value in some data storage suitable for signed int values which might be located somewhere completely different. That data storage does not contain any useful value because the compiler wrote the value of a somewhere else!







        share|cite|improve this answer














        share|cite|improve this answer



        share|cite|improve this answer








        edited May 15 at 20:09

























        answered May 15 at 20:04









        Martin RosenauMartin Rosenau

        1756




        1756













            Popular posts from this blog

            Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

            Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

            What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company