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

            Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

            Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

            Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020