Programming => General => Topic started by: fcu on April 10, 2020, 12:06:17 pm

Title: c to pascal
Post by: fcu on April 10, 2020, 12:06:17 pm
this c code print number 8 ,even i don't understand how c compiler evaluate this line !! 
Code: C  [Select][+][-]
  1.   char c = 7 + '1';
  2.   printf("%c ",c);

now by curiosity i tried to convert this to fpc , i don't think its possible ?
Title: Re: c to pascal
Post by: PascalDragon on April 10, 2020, 12:19:10 pm
The reason why C does print 8 is rather simple: it increases the ASCII value of '1' by 7 which happens to be '8'. If you'd increase it by 9 you'd get ':', because that is the character after '9'. This is this way in C, because while char more often than not is used for character strings it is also the equivalent to Pascal's ShortInt (as char is signed char). Due to this normal integer arithmetic works there as well.

Pascal as stricter typing however. So for something similar you'll have to cast:

Code: Pascal  [Select][+][-]
  1. var
  2.   c: Char;
  3. begin
  4.   c := Chr(7 + Ord('1'));
  5.   Writeln(c);
  6. end;

Or define a suitable operator overload:

Code: Pascal  [Select][+][-]
  1. // note: you'll need to define the other way round as well
  2. // as overloads are not commutative by themselves
  3. operator + (aLeft: ShortInt; aRight: Char) Res : Char;
  4. begin
  5.   Res := Chr(aLeft + Ord(aRight));
  6. end;
  8. var
  9.   c: Char;
  10. begin
  11.   c := 7 + '1';
  12.   Writeln(c);
  13. end.
Title: Re: c to pascal
Post by: fcu on April 10, 2020, 12:31:28 pm
aha, many thanks
c is a mysterious world , your pascal code is self readable and show how pascal evaluate this expression
this explicit casting make things clearer :) thanks   
Title: Re: c to pascal
Post by: marcov on April 10, 2020, 02:19:54 pm
aha, many thanks
c is a mysterious world , your pascal code is self readable and show how pascal evaluate this expression
this explicit casting make things clearer :) thanks   

That is the positive spin. the negative one is that it is now abandonware :-)
Title: Re: c to pascal
Post by: Warfley on April 11, 2020, 01:22:52 pm
Minor nitpick to PascalDragons answer, char in C is not neccesarily signed char, but either signed or unsinged char. This is open to be chosen by tha compiler, which is faster for the target architecture.

Also what should be noted is that C has differentiates between chars and string literals on a syntactic level. Single quotes like here denote a char, while double quote denote a string.
Combined with the fact that C does not have a concept of chars, they are basically only syntactic sugar for writing numbers. Writing 'A' is the same as writing 65. C also doesn't have a concept of strings. String literals are therefore only syntactic sugar for character arrays where the last element is 0.
Code: C  [Select][+][-]
  1. char abc[] = "ABC";
  2. // Is the same as
  3. char abc[] = {'A', 'B', 'C', 0};
  4. // Is the same as
  5. char abc[] = {65, 66, 67, 0};
And arrays can be interpreted as pointer, which results in funny results when you accidentally think you are working with a higher level language and try to use arithmetic on them
Code: C  [Select][+][-]
  1. char *str = "ABC";
  2. char *str2 = "DEF";
  3. char *result = str1 + str2; // This is not "ABC"+"DEF" but the sum of both pointers, and will most likely end in a segfault when used

C++ tries to fixes this by introducing the std::string type, which is much closer to pascal strings (It's not lazy, but aside from this they are pretty equivalent).

Pascal on the other hand has a built in support for chars and strings. Chars for example are their own type, which is different from integers. For example
Code: Pascal  [Select][+][-]
  1. if #65 = 65 then
yields a compiler error as the char with value 65 is not comparable to the number 65. Pascal also has a string type, and chars can implicetly be converted into Strings, meaning 'A' + 'B' does not yield the char with value 65+66 but a String containing two chars A and B.
From a black box view chars could be implemented completely different from integers, e.g. using unicorn farts, and the conversion is using functions like Ord and Chr.
I'm not a compiler developer, but I think unicorn fart technology isn't so sophisticated right now, so internally chars should still be implemented as 8 bit integers and Ord and Chr are therefore only "compiler macros" to make the type checking happy. But for all you as a user could know, this could be changed in the next version of the FPC and your code would still work.

C is a lower level language than Pascal, that does many things as how it would be done in assembler. Another example would be that C has no boolean type, comparisons result only in integers. Your code basically adds two numbers and printf then decides at runtime (with the %c) that this number should be interpreted as a char. Also there is no equivalent to your code in Pascal, because there is no function in the whole RTL thats so "fucked up" as printf is. But to emulate that code as close as possible you need to convert between chars and integers/bytes.

To end this post I'll leave you this gem of a base64 decode function written with all of the glory C has to offer:
Code: C  [Select][+][-]
  1. unsigned char decodeB64Char (char c) {
  2.     return c > '9'
  3.       ? (c > 'Z'
  4.         ? c - 71
  5.         : c - 65
  6.       ) : (c >= '0'
  7.         ? c  + 4
  8.         : (c == 47
  9.           ? 62
  10.           : 63
  11.         )
  12.       );
  13. }
  15. void decodeBase64(char *str, char *result, int maxLen) {
  16.     unsigned char decoded;
  17.     int i, idx, offset;
  18.     int b64len = strlen(str);
  19.     for (i=0, idx=0, offset=0, decoded=decodeB64Char(str[i]);
  20.          (idx<maxLen) && (i<b64len) && (str[i] != '=');
  21.          decoded =
  22.          ((offset =
  23.            ((idx =
  24.              ((result[idx + 1] |=
  25.                ((result[idx] |= (decoded >> offset) & 255),
  26.                 decoded << (8-offset)) & 255),
  27.               idx + (offset >=2))),
  28.             (offset + 6) % 8)),
  29.           decodeB64Char(str[++i])));
  30. }
TinyPortal © 2005-2018