C


Limits

https://en.cppreference.com/w/c/types/limits

Type Min value Max value
char CHAR_MIN CHAR_MAX
signed char SCHAR_MIN SCHAR_MAX
unsigned char UCHAR_MIN UCHAR_MAX
short SHRT_MIN SHRT_MAX
unsigned short USHRT_MIN USHRT_MAX
int INT_MIN INT_MAX
unsigned int UINT_MIN UINT_MAX
long LONG_MIN LONG_MAX
unsigned long ULONG_MIN ULONG_MAX
long long LLONG_MIN LLONG_MAX
unsigned long long ULLONG_MIN ULLONG_MAX

scanf

Use of scanf() is usually frowned upon as it doesn't give the programmer enough control over what could happen (Eg: buffer overflow attack).

Yet, it's quite useful to get stuff done quick when you are just messing around with C while learning it.

In that sense, scanf() is in fact, quite useful.

Format specifiers

FS Type
%zu size_t
%n Number of chars written so far
%o Octal
%% Literal '%'
%c char
%d int
%s string
%f int
%n a special one
%d int
%u unsigned int
%p address (pointer)
%x int as hexadecimal (0x, 0X, ,)
%X int as hexadecimal (0x, 0X, ,)
%[^\n] Exclude (till \n)

Modifiers:

Format specifier Type
%ld long int
%lld long long int
%lf double
%lu long unsigned

See: https://en.cppreference.com/w/c/io/fprintf

Interesting behavior and facts

In my UG days, I spent a lot of time with the C programming language. Had forgotten most of it.

But now (Feb 2023) I'm a TA for a lab course using C. Noting down stuff that I came across again..

No evaluation within sizeof

#include<stdio.h>

int main() {
    int a=3, b;
    b = sizeof(a=10);
    printf("a=%d, b=%d\n", a, b);
    // a=3, b=4

    // Value of b is compiler/arch dependent though.

    return 0;
}

(Thanks to Kevin for telling me this.)

Expression inside sizeof is not evaluated. So the value of a never changed.

In sizeof(a=10), type of a=10 is looked at. It is found to be int. So essentially, it is same as saying sizeof(int) or sizeof(10), I guess.

sizeof(int) is usually 4, but can be different depending on architecture and compiler.

Multiple sequence points

Multiple sequence points => undefined behaviour.

#include<stdio.h>

int main() {
    int a=3;
    printf("%d\n", a++ + ++a);
    // 8

    // Needn't be so though. It's undefined behaviour.

    return 0; 
}

Evaluation could be like:

(Thanks to Kevin for reminding me about this.)

Calling main from main

Looks like this is possible in C (gcc).

#include<stdio.h>

int ctr = 5;

int main() {
    if(ctr>0) {
        printf("Hi\n");
        ctr--;
        main();
    }
}

/*
Hi
Hi
Hi
Hi
Hi
*/

Apparently, C++ standard prohibits this but gcc allows it.

Digraphs

Digraph Equivalent
<: [
:> ]
<% {
%> }
%: #
%:%: ##

Trigraphs

Trigarph Result
??= #
??( [
??/ \
??) ]
??' ^
??< {
??!
??> }
??- ~

C pre-processor (CPP)

// Check if a macro is defined
#ifdef NAME
  print("NAME is defined\n");
#else
  print("NAME is not defined\n");
#endif