C serial 20 – exceptions in conversion description

Time:2022-5-14

1、 Use formatted output for Strings

#include
#define BLURB "Authentic imitation!"

int D20_1_stringf(void) {
	printf("[%2s]\n", BLURB);
	printf("[%24s]\n", BLURB);
	printf("[%24.5s]\n", BLURB);
	printf("[%-24.5s]\n", BLURB);

	return 0;
}

20.1

  • Interpretation: the decimal point is followed by a number, which means that several characters will be output. The one in front of the decimal point indicates how many spaces are occupied, and the minus sign represents the left aligned output of the text.
  • The following shows several programs with mismatched conversion instructions
#include
#define PAGES 336
#define WORDS	65618
int D20_2_intconv(void) {
	short num = PAGES;
	short mnum = -PAGES;

	printf("num as short and unsigned short:%hd %hu\n", num, num);
	printf("-num as short and unsigned short:%hd %hu\n", mnum, mnum);
	printf("num as int and char:%d %c\n", num, num);
	printf("WORDS as int,short, and char: %d %hd %c\n", WORDS, WORDS, WORDS);

	return 0;
}

20.2

  • Interpretation: the first line represents short decimal numbers and short unsigned decimal numbers. Obviously, the size range of numbers is within short; In the second line, the first one is in the range of short, and the second short int is two self. Negative numbers are stored in memory in the form of complements, but%hu can be positive numbers, so the complements of negative numbers are given out according to normal binary; The third and fourth lines are beyond the corresponding range, and the numbers are truncated accordingly.

2、 Confusing integer and floating-point types makes the result even more strange

#include
int D20_3_floatcnv(void) {
	float n1 = 3.0;
	double n2 = 3.0;
	long n3 = 2000000000;
	long n4 = 1234567890;

	printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
	printf("%ld %ld\n", n3, n4);
	printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);

	return 0;
}

20.3

  • Definition:% e conversion Description: integer is not converted to floating point number. When printing first, it will be converted to eight bit floating point number. The original long type is four bits, so the system will take the adjacent four bit memory, resulting in unexpected numbers; The third line is OK; The fourth line is puzzling. Even using the correct conversion description will produce false results. Using% LD conversion means that printing floating-point numbers will fail, but here, printing long numbers with% LD also fails,The problem is how C passes information to functions. The specific situation varies with the compiler implementation. A representative system is discussed in the “parameter passing” box

Parameter passing: take the third behavior example of the above program for analysis. The program puts the incoming values into a memory area called stack, and the computer puts these values into the stack according to the variable type (not according to the conversion description). Therefore, N1 is stored in the stack, accounting for 8 bytes (float type is converted to double type). Similarly, N2 also occupies 8 bytes in the stack, while N3 and N4 occupy 4 bytes respectively. Then the control goes to printf() function, which reads data from the stack according to the conversion description (not according to the variable type),% LD conversion description means to read 4 bytes, so printf() reads the first 4 bytes in the stack as the first value. This is the first half of N1, which will be interpreted as a long integer. According to the next% LD conversion description, printf() will then read 4 bytes. This is the second half of N1, which will be interpreted as an integer of the second long type. Similarly, errors will occur when reading the last two variables.

2、 Source code: