Cover image for C

C


Timeline

Timeline

2025-07-19

init

This article introduces the basics of the C language, summarizing in detail the byte sizes, value ranges, and cross-platform differences of common integer data types. Additionally, it discusses the specific usage of input/output library functions, focusing on the handling mechanism of %c and whitespace characters in the scanf function, the parameters, return values, and cross-platform compatibility issues of the getline function, as well as the format tags and output meanings of various format characters in the printf function.

Data Types

Common Integer Ranges

Data TypeByte SizeDecimal Value RangeScientific Notation (Approximate)
char1-128 ~ 127-1.28×10² ~ 1.27×10²
unsigned char10 ~ 2550 ~ 2.55×10²
short2-32,768 ~ 32,767-3.28×10⁴ ~ 3.27×10⁴
unsigned short20 ~ 65,5350 ~ 6.55×10⁴
int4-2,147,483,648 ~ 2,147,483,647-2.15×10⁹ ~ 2.15×10⁹
unsigned int40 ~ 4,294,967,2950 ~ 4.29×10⁹
long(Linux 64-bit)8-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807±9.22×10¹⁸
unsigned long80 ~ 18,446,744,073,709,551,6150 ~ 1.84×10¹⁹
long long8-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807±9.22×10¹⁸
unsigned long long80 ~ 18,446,744,073,709,551,6150 ~ 1.84×10¹⁹
  • The byte size of long may vary across different platforms; for example, on a 64-bit Linux system, it is typically 8 bytes.
  • The actual size and range are determined by the compiler and the target platform’s data model, such as LP64 (Linux) / LLP64 (Windows).

ASCII Table

ASCII Printable Characters
ASCII Printable Characters

ASCII Control Characters
ASCII Control Characters

Library function

Input/Output

scanf

Difference between %c and whitespace

1
scanf("%c", &ch);

Will read a character verbatim, including spaces, tabs, and newline \n.

1
scanf(" %c", &ch);

Because there is a space in the format string, scanf will first skip all whitespace characters (space, \t, \n), then read a valid character.

1
while(scanf("%d",&x)!=EOF)

Summary:

  • scanf returns EOF when reading an invalid value
  • %d, %f and other numeric format specifiers: automatically skip whitespace by default.
  • %c: does not skip whitespace; need " %c" to ignore spaces and newlines.
  • Principle: In scanf’s format string, whitespace characters (space, \n, \t) mean ‘match any amount of whitespace’.

getline

The return value of getline() is the number of characters read (including the newline)

ParameterMeaning
char **lineptrPoints to achar*pointer (used to store the read string; the function automatically allocates/expands memory internally)
size_t *nPointer to buffer size (initially 0); the function dynamically allocates/expands memory as needed
FILE *streamInput stream, e.g.,stdin, file handle, etc.

Return value

  • Success: returns the number of characters read (including newline\n, but excluding the null terminator\0
  • Failure: returns-1, and setserrno

Using getline requires including <stdio.h> and <stdlib.h> as defined by GNU extensions, but more critically, on some non-POSIX platforms (such as Windows or older standard C compilers), getline() is not a standard C function.
Comprehensive solution (applicable to Linux/GCC environment):
Ensure you include the following header files:

1
2
3
4
5
6
7
8
9
10
11
12
// Optional: enable GNU extensions
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>

// Using strcspn
#include <string.h>

// Defines the ssize__t type (signed size_t), commonly used as the return value of functions like read, write, getline, readlink
// is part of the POSIX standard, not part of the C standard library, so it must be included when using POSIX APIs on GNU/Linux platforms
#include <unistd.h>

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define _GNU_SOURCE         // Enable GNU extensions required by getline
#include <stdio.h>
#include <stdlib.h>
#include <errno.h> // Provide errno
#include <string.h> // Provide strerror()

int main() {
char *line = NULL;
size_t len = 0;
ssize_t nread;

printf("请输入一行文本(按 Ctrl+D 或 Ctrl+Z + Enter 结束):\n");

errno = 0; // Clear before use
nread = getline(&line, &len, stdin);

if (nread == -1) {
if (feof(stdin)) {
printf("输入结束(EOF)\n");
} else {
// Print the value of errno and its corresponding information
fprintf(stderr, "getline 失败,errno = %d: %s\n", errno, strerror(errno));
}
free(line);
return 1;
}

printf("读取了 %zd 字符:%s", nread, line);
free(line);
return 0;
}

printf

Detailed explanation of the printf function:
Below is the declaration of the printf() function.

1
int printf(const char *format, ...)

Parameters

  • format – This is a string that contains the text to be written to stdout. It can contain embedded format tags, which are replaced by the values specified in subsequent additional arguments and formatted as required.
  • The format tag attributes are
1
%[flags][width][.precision][length]specifier
Format characterMeaning
a, AOutput floating-point number in hexadecimal (new in C99). Exampleprintf(“pi=%a\n”, 3.14);Outputpi=0x1.91eb86p+1
dOutput signed integer in decimal (positive numbers do not output sign)
oOutput unsigned integer in octal (without prefix 0)
x,XOutput unsigned integer in hexadecimal (without prefix 0x)
uOutput unsigned integer in decimal
fOutput single or double precision real number in decimal form
e,EOutput single or double precision real number in exponential form
g,GOutput single or double precision real number using the shorter of %f or %e
cOutput a single character
sOutput a string
pOutput pointer address
lu32-bit unsigned integer
llu64-bit unsigned integer
flagsDescription
-Left-align within the given field width; right alignment is the default (see width sub-specifier).
+Forces a plus or minus sign (+ or -) to appear before the result, i.e., positive numbers will show a + sign. By default, only negative numbers are preceded by a - sign.
SpaceIf no sign is written, a space is inserted before the value.
#When used with o, x, or X specifiers, a non-zero value is preceded with 0, 0x, or 0X respectively. When used with e, E, and f, it forces the output to contain a decimal point even if no digits follow. By default, if no digits follow, no decimal point is shown. When used with g or G, the result is the same as with e or E, but trailing zeros are not removed.
0Pad with zeros (0) instead of spaces to the left of the number (see width sub-specifier).
WidthDescription
(number)Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with spaces. If the value is longer, the result is not truncated.
*The width is not specified in the format string, but as an additional integer value argument placed before the argument to be formatted.
.precisionDescription
.numberFor integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter, the result is padded with leading zeros. If the value is longer, the result is not truncated. A precision of 0 means no character is written. For e, E, and f specifiers: the number of digits to be printed after the decimal point. For g and G specifiers: the maximum number of significant digits to be printed. For s: the maximum number of characters to be printed. By default, all characters are printed until the terminating null character. For c type: has no effect. When no precision is specified, the default is 1. If specified without an explicit value, it is assumed to be 0.
.*The precision is not specified in the format string, but as an additional integer value argument placed before the argument to be formatted.
lengthDescription
hThe argument is interpreted as a short int or unsigned short int (only applies to integer specifiers: i, d, o, u, x, and X).
lThe argument is interpreted as a long int or unsigned long int, applicable to integer specifiers (i, d, o, u, x, and X) and specifiers c (for a wide character) and s (for a wide character string).
LThe argument is interpreted as a long double (only applies to floating-point specifiers: e, E, f, g, and G).
  • Additional arguments

Depending on the format string, the function may require a series of additional arguments, each containing a value to be inserted, replacing each % tag specified in the format parameter. The number of arguments should match the number of % tags.

  • Return value

On success, returns the total number of characters written; otherwise, returns a negative number.

math.h

Error status macro definitions

In<math.h>, there are macros used to represent the error status of mathematical functions:

MacroDescription
HUGE_VALThe value returned when the function result overflows (positive infinity). This macro represents a very large double-precision floating-point number, typically used as the return value for certain mathematical functions when the result exceeds the representable range. When a function’s result is too large to be represented as a normal floating-point number (i.e., overflow occurs), errno is set to ERANGE (range error), and HUGE_VAL or its negative (for negative infinity) is returned.
HUGE_VALFValue returned when the function result overflows (positive infinity, floating-point)
HUGE_VALLValue returned when the function result overflows (positive infinity, long double)
INFINITYPositive infinity
NANNot-A-Number
FP_INFINITERepresents infinity
FP_NANRepresents Not-A-Number
FP_NORMALRepresents a normal floating-point number
FP_SUBNORMALRepresents a subnormal number
FP_ZERORepresents zero

Library functions

The following lists the functions defined in the header file math.h:

FunctionDescription
double acos(double x)Returns the arccosine of x in radians.
double asin(double x)Returns the arcsine of x in radians.
double atan(double x)Returns the arctangent of x in radians.
double atan2(double y, double x)Returns the arctangent of y/x in radians. The signs of y and x determine the correct quadrant.
double cos(double x)Returns the cosine of radian angle x.
double cosh(double x)Returns the hyperbolic cosine of x.
double sin(double x)Returns the sine of radian angle x.
double sinh(double x)Returns the hyperbolic sine of x.
double tanh(double x)Returns the hyperbolic tangent of x.
double exp(double x)Returns the value of e raised to the power of x.
double frexp(double x, int *exponent)Breaks the floating-point number x into a mantissa and an exponent. The return value is the mantissa, and the exponent is stored in exponent. The resulting value is x = mantissa * 2^exponent.
double ldexp(double x, int exponent)Returns x multiplied by 2 raised to the power of exponent.
double log(double x)Returns the natural logarithm (base e) of x.
double log10(double x)Returns the common logarithm (base 10) of x.
double modf(double x, double *integer)Returns the fractional part (the part after the decimal point) and sets integer to the integer part.
double pow(double x, double y)Returns x raised to the power of y.
double sqrt(double x)Returns the square root of x.
double ceil(double x)Returns the smallest integer value greater than or equal to x.
double fabs(double x)Returns the absolute value of x.
double floor(double x)Returns the largest integer value less than or equal to x.
double fmod(double x, double y)Returns the remainder of x divided by y.
Function NamePurposeRounding Direction
round()Round to NearestTo Nearest Integer
floor()Round Down (largest integer not greater than the original number)Towards -∞
ceil()Round Up (smallest integer not less than the original number)Towards +∞
trunc()Truncate (remove fractional part)Towards 0

Commonly Used Mathematical Constants

The following are<math.h>some commonly used mathematical constants defined in

ConstantValueDescription
M_PI3.14159265358979323846Pi π
M_E2.71828182845904523536Base of natural logarithm e
M_LOG2E1.44269504088896340736log2(e)
M_LOG10E0.43429448190325182765log10(e)
M_LN20.69314718055994530942ln(2)
M_LN102.30258509299404568402ln(10)
M_PI_21.57079632679489661923π/2
M_PI_40.78539816339744830962π/4
M_1_PI0.318309886183790671541/π
M_2_PI0.636619772367581343082/π
M_2_SQRTPI1.128379167095512573902/√π
M_SQRT21.41421356237309504880√2
M_SQRT1_20.707106781186547524401/√2

string.h

strdup

1
2
#include <string.h>
char *strdup(const char *s);

Equivalent to strcpy but automatically allocates memory

strtok

1
char *strtok(char *str, const char *delim)

Parameters
str: The string to be split. On the first call, pass the string to be split; on subsequent calls, pass NULL to continue splitting the same string.
delim: The delimiter string. strtok() splits str based on any character in this string.

Return Value
Returns a pointer to the next token. If there are no more tokens, returns NULL.

1
2
3
4
5
6
7
8
9
/* Get the first substring */
token = strtok(str, s);

/* Continue to get other substrings */
while( token != NULL ) {
printf( "%s\n", token );

token = strtok(NULL, s);
}

Notes

  1. Modifies the original string: strtok() modifies the passed string, replacing delimiters with \0 (null character). Therefore, the original string is destroyed.
  2. Non-reentrant: strtok() uses a static buffer to save state, so it is not thread-safe. If used in a multi-threaded environment, consider using strtok_r() (the reentrant version).
  3. Consecutive delimiters: If there are consecutive delimiters in the string, strtok() ignores them and returns the next valid token.

Reentrant version: strtok_r()
strtok_r() is the reentrant version of strtok(), allowing safe use in multi-threaded environments. Its prototype is as follows:

char *strtok_r(char *str, const char *delim, char *saveptr);
saveptr: is a pointer to char
used to save the splitting state.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>

int main() {
char str[] = "This is a sample string";
char *token;
char *saveptr;

// First call to strtok_r, passing the string to be split
token = strtok_r(str, " ", &saveptr);

// Continue calling strtok_r until it returns NULL
while (token != NULL) {
printf("%s\n", token);
token = strtok_r(NULL, " ", &saveptr);
}

return 0;
}

strcspn

strcspn is a string handling function in the C standard library <string.h>, used to find the position of the first character in the target string that matches any character in a specified set.

  • Function prototype
1
2
3
#include <string.h>

size_t strcspn(const char *s, const char *reject);
  • Function description

It returns the position (index) of the first character in string s that matches any character in reject; if s contains no characters from reject, it returns strlen(s).

💡 “cspn” stands for complement span, meaning: returns the length of the longest prefix that is not in reject

  • Example
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <string.h>

int main() {
char str[] = "hello, world!";
size_t pos = strcspn(str, ",!");

printf("第一个 ',' 或 '!' 的位置是:%zu\n", pos); // Output 5
return 0;
}

strspn

strspn is a function in the C standard library <string.h> that calculates how many characters at the beginning of a string all belong to a specified set of characters.
The function name strspn comes from the abbreviation of “string span”, meaning “the span of a string” or “the length of a consecutive prefix in a string that meets a condition”.

Compare with strcspn

Function NameMeaning Description
strspnspan of characters in accept
strcspnspan of characters not in reject

That is:

  • strspn(s, accept): counts how many characters from the beginning are in accept

  • strcspn(s, reject): counts how many characters from the beginning are not in reject

  • Function Prototype

1
2
3
#include <string.h>

size_t strspn(const char *s, const char *accept);
  • Function Description

strspn(s, accept) returns how many consecutive characters at the beginning of string s all appear in accept.

  1. It does not skip characters, nor does it check the entire string;
  2. Once a character not in accept is encountered, stop counting;
  3. The return value is of type size_t (i.e., an unsigned integer), representing the length of the match.
  • Example
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <string.h>

int main() {
const char *s = "abcabc123";
const char *accept = "abc";

size_t len = strspn(s, accept);
printf("前缀长度为:%zu\n", len); // Output 6
return 0;
}
  • ✨ Analysis:
    String s = “abcabc123”
    Starting with ‘a’, ‘b’, ‘c’, exactly 6 consecutive characters are all in “abc”
    The 7th character is ‘1’, not in “abc” → counting stops
    So it returns 6

  • Use Cases
    📌 Check if the beginning of a string contains only certain characters

1
2
3
if (strspn(s, "0123456789") == strlen(s)) {
printf("s 是纯数字\n");
}

📌 Skip all valid characters in the prefix

1
2
3
char *s = " \t\n hello";
s += strspn(s, " \t\n"); // Skip all whitespace characters
printf("剩下:%s\n", s); // Output "hello"

Error Handling

errno

When a standard library function call fails, you can readerrnoto determine thespecific cause of the failure, and then useperror()orstrerror(errno)to get the corresponding error description.


Example: Useerrno

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main() {
FILE *fp = fopen("no-such-file.txt", "r");
if (fp == NULL) {
// print error number
printf("errno = %d\n", errno);

fprintf(stderr, "error code = %d\n", errno);

// print error description
perror("fopen 失败"); // Recommended: automatically add prefix

// or manually print error message
printf("错误信息: %s\n", strerror(errno));
}
return 0;
}

Output:

1
2
3
4
errno = 2
error code = 2
fopen 失败: No such file or directory
错误信息: No such file or directory