Cover image for C

C

Words 3.2k
Views
Visitors

Timeline

Timeline

2025-07-19

init

This article introduces the basics of the C language, focusing on the byte sizes and value ranges of common integer types, and points out that the differences of the long type across platforms are determined by data models (such as LP64, LLP64). The article also covers the ASCII table, library functions, and input/output operations, detailing the difference in handling %c and whitespace characters in the scanf function, as well as the usage and return value of the getline function. In addition, the format specifiers of the printf function are listed and explained.

Data Type

Common integer ranges

Data TypeByte countDecimal rangeScientific notation (approx.)
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 differ across platforms; for example, it is usually 8 bytes on 64-bit Linux systems.
  • 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 functions

Input/Output

scanf

Difference between %c and whitespace

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

It reads one character as-is, including spaces, tabs, and newline \n.

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

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

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

Summary:

  • scanf returns EOF if an input failure occurs (such as end-of-file) before any conversion is performed; if a matching failure occurs after some conversions, it returns the number of items successfully matched (possibly 0).
  • Numeric format specifiers such as %d, %f: whitespace is automatically skipped by default.
  • %c: does not skip whitespace; you need " %c" to ignore spaces and newlines.
  • Principle: In scanf’s format string, a whitespace character (space, \n, \t) means “match any amount of whitespace”.

getline

The return value of getline() is the number of characters read (including the newline, excluding the terminator\0); on failure it returns -1. getline is a POSIX function, not a standard C function.

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

Return value

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

Using getline requires including<stdio.h>and<stdlib.h>, but more importantly, on some non-POSIX platforms (such as Windows or older standard C compilers), getline() is not available.
Comprehensive solution (applicable to Linux/GCC environment):
Make sure to include the following header files:

123456789101112
// Optional: enable GNU extensions#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>// Use strcspn#include <string.h>// defines the ssize_t type (signed size_t), commonly used as the return value of functions such as read, write, getline, readlink// is part of the POSIX standard, not part of the C standard library. On GNU/Linux platforms, when using POSIX APIs, this type can be obtained by including <unistd.h> or <sys/types.h>#include <unistd.h>

Example:

1234567891011121314151617181920212223242526272829303132
#define _GNU_SOURCE         // Enable the GNU extensions required by getline#include <stdio.h>#include <stdlib.h>#include <errno.h>          // Provides errno#include <string.h>         // Provides strerror()int main() {    char *line = NULL;    size_t len = 0;    ssize_t nread;    printf("请输入一行文本(按 Ctrl+D 或 Ctrl+Z + Enter 结束):\n");    errno = 0;  // Clear to zero before use    nread = getline(&line, &len, stdin);    if (nread == -1) {        if (feof(stdin)) {            printf("输入结束(EOF)\n");        } else {            // Print the value of errno and the 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 the standard output stdout. It can contain embedded format tags, which can be replaced by the values specified in the subsequent additional arguments and formatted as required.
  • The format tag attributes are
1
%[flags][width][.precision][length]specifier
Format characterMeaning
a, AOutput floating-point numbers in hexadecimal form (new in C99). Example printf(“pi=%a\n”, 3.14); output pi=0x1.91eb86p+1
dOutput signed integers in decimal form (positive numbers do not output the sign)
oOutputs an unsigned integer in octal form (without outputting the prefix 0)
x,XOutputs an unsigned integer in hexadecimal form (without outputting the prefix 0x)
uOutputs an unsigned integer in decimal form
fOutputs single- or double-precision real numbers in decimal notation
e,EOutputs single- or double-precision real numbers in exponential notation
g,GAutomatically selects the more compact of %f or %e to output single- or double-precision real numbers
cOutputs a single character
sOutputs a string
pOutputs a pointer address
luLength modifier for %u, outputs unsigned long
lluLength modifier for %u, outputs unsigned long long
flagsDescription
-Left-aligns the output within the given field width; right-alignment is the default (see width sub-specifier).
+Forces a plus or minus sign (+ or -) to be shown before the result, i.e., positive numbers are preceded by 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 by 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, the decimal point is not shown. When used with g or G, the result is the same as with e or E, but trailing zeros are not removed.
0Places zeros (0) to the left of the number instead of spaces when padding is specified (see width sub-specifier).
widthDescription
(number)Minimum number of characters to be output. If the output value is shorter than this number, the result is padded with spaces. If the output value is longer than this number, the result is not truncated.
*The width is not specified in the format string, but is given 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 written is shorter than this number, the result is padded with leading zeros. If the value written is longer than this number, the result is not truncated. When precision is 0 and the value is 0, no characters are written; otherwise, it is output normally. For e, E, and f specifiers: the number of digits to be output after the decimal point. For g and G specifiers: the maximum number of significant digits to be output. For s: the maximum number of characters to be output. By default, all characters are output until the terminating null character is encountered. For c type: 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 is given 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 (denoting a wide character) and s (denoting 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 be the same as the number of % tags.

  • Return value

    If successful, returns the total number of characters written; otherwise, returns a negative number.

math.h

Error status macro definitions

Before<math.h>Among them, there are some 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, usually 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., an overflow occurs), errno is set to ERANGE (range error), and HUGE_VAL or its negative value (for negative infinity) is returned.
HUGE_VALFThe value returned when the function result overflows (positive infinity, float type)
HUGE_VALLThe value returned when the function result overflows (positive infinity, long double)
INFINITYPositive infinity
NANNot-A-Number (NaN)
FP_INFINITERepresents infinity
FP_NANRepresents a non-numeric value
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 the values of y and x determine the correct quadrant.
double cos(double x)Returns the cosine of the radian angle x.
double cosh(double x)Returns the hyperbolic cosine of x.
double sin(double x)Returns the sine of x, where x is in radians.
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 of x (logarithm to base e).
double log10(double x)Returns the common logarithm of x (logarithm to base 10).
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 nameFunctionRounding direction
round()Round half upTo nearest integer
floor()Round down (the largest integer not greater than the original number)Toward -∞
ceil()Round up (the smallest integer not less than the original number)Toward +∞
trunc()Remove the fractional part (truncate)Toward 0

Common mathematical constants

The following are<math.h>Some common mathematical constants defined in:

ConstantValueDescription
M_PI3.14159265358979323846Pi (π)
M_E2.71828182845904523536The base of the 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

12
#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.

123456789
/* Get the first substring */token = strtok(str, s);/* Continue getting the remaining 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 corrupted.
  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(), which allows you to use it safely in multi-threaded environments. Its prototype is as follows:

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

Example:

12345678910111213141516171819
#include <stdio.h>#include <string.h>int main() {    char str[] = "This is a sample string";    char *token;    char *saveptr;    // Call strtok_r the first time, 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> that finds the position of the first character in the target string that matches any character in the specified character set.

  • Function prototype
123
#include <string.h>size_t strcspn(const char *s, const char *reject);
  • Description

It returns the position (index) of the first character in string s that is also in reject. If s contains none of the characters in reject, it returns strlen(s).

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

  • example
12345678910
#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 counts how many characters at the beginning of a string all belong to the specified character set.
The function name strspn is an abbreviation of ‘string span’, meaning ‘the span of a string’ or ‘the length of a contiguous prefix of a string that satisfies a condition’.

Compare with strcspn

function nameMeaning description
strspnspan of characters in accept
strcspnspan of characters not in reject

In other words:

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

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

  • Function prototype

123
#include <string.h>size_t strspn(const char *s, const char *accept);
  • Description

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

  1. It does not skip characters, nor does it examine the entire string;
  2. As soon as it encounters a character not in accept, it stops counting;
  3. The return value is of type size_t (that is, an unsigned integer), representing the length of the match.
  • example
1234567891011
#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 in “abc”.
    The 7th character is ‘1’, which is not in “abc” → counting stops.
    So it returns 6.

  • Application scenarios
    📌 Check whether the beginning of a string contains only certain characters

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

📌 Skip all valid characters in the prefix

123
char *s = " \t\n hello";s += strspn(s, " \t\n");  // Skip all whitespace charactersprintf("剩下:%s\n", s);  // Output: "hello"

Error handling

errno

You can, when a standard library function call fails, readerrnothe value of … to determine the failure’sspecific reason, and then useperror()orstrerror(errno)to get the corresponding error description.


Example: Usageerrno

12345678910111213141516171819202122
#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:

1234
errno = 2error code = 2fopen 失败: No such file or directory错误信息: No such file or directory
Loading comments…