달력

112024  이전 다음

  • 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
검색하다보니 아래 싸이트를 찾을 수 있었다.

http://klausler.com/cnotes.txt


좋은 정보라고 생각한다.
개인 홈페이지 내 파일 같은데 링크가 사라질까봐 무단으로 복사해서 덧붙인다.
Peter Klausler 님.... 감사합니다 ^^;;




Some things every C programmer should know about C
PMK 10-16-2002


Types
-----

Every constant, object, function, and expression in C has a type.
Most generally, a type is either an unqualified type or such a type
qualified with "const", "volatile", or both qualifiers.  Unqualified
types comprise three categories:

	Object types
		Scalar
		   Arithmetic
		      Integral
		         signed/unsigned/plain
		            character types
		            short, int, long
		         bitfield
		         enumeration
		      Floating-point
		   Pointer to general type
		Aggregate
		   struct/union of object types and bitfields
		   known-size array of objects
	Incomplete types
		void
		undefined struct/union
		array of unknown size of objects
		array of incomplete type (except void)
	Function returning void or unqualified object type (except array)
		(with no arguments, with unknown or old-style arguments, or
		 with prototyped arguments of general types)

Bitfields may appear only as struct/union members, so
there are no pointers to bitfields, arrays of bitfields, or
functions taking or returning bitfields.

Some types are silently replaced.  A qualified array type becomes
an unqualified array of the qualified type, and function arguments
that are arrays or functions become pointers.


Declarator Syntax
-----------------

Binding is just like expressions: postfix before prefix.  So
parentheses are necessary in declarators only for function arguments
and for pointers to functions and arrays!

In qualified pointer types, the pointer qualifiers appear after the *.

How to easily read a declaration from left to right:
	transform function argument types from inside out first
	move the base type to the end
	add outer parentheses if there's an initial *
	change every (*...) to ... ->
		one -> for each *
		move qualifiers, so * const becomes const ->

Example: const int *(**const x [])()

	*(**const x [])() const int		base type to end
	(*(**const x [])()) const int		add outer parens
	(**const x [])() -> const int		remove outer ()
	x [] const -> -> () -> const int	remove inner ()

	array of constant pointers to pointers to functions
	returning pointers to constant ints


Types of Constants
------------------

Floating-point constants are "double" unless suffixed by 'F' or 'L'.

Integer constants take the first type that fits in one of these lists:
	with 'U':	unsigned int, unsigned long
	with 'L':	long, unsigned long
	with 'UL':	unsigned long
	decimal:	int, long, unsigned long
	octal, hex:	int, unsigned int, long, unsigned long
(So 2147483648 is long but 0x80000000-0xffffffff are unsigned int.)

Character constants are "int".
String literals are arrays of "char".

Null pointer constants:
	any zero-valued integral constant expression,
	possibly cast to (void *)


Operator Precedence and Associativity
-------------------------------------

These are the classes of operators in decreasing order of precedence.

	(x)
	postfix:	x[y], x(...), x.y, x->y, x++, x--
	prefix:		++x, --x, (type) x, sizeof x, &x, *x, +x, -x, ~x, !x
	multiplicative:	x*y, x/y, x%y
	additive:	x+y, x-y
	shift:		x<<y, x>>y
	relational:	x<y, x<=y, x>y, x>=y
	equality:	x==y, x!=y
	bitwise and:	x&y
	bitwise xor:	x^y
	bitwise or:	x|y
	logical and:	x&&y
	logical or:	x||y
	conditional:	x?y:z
	assignment:	x=y and *= /= %= += -= <<= >>= &= ^= |=
	sequence:	x,y

All binary operators are left-associative where it makes a difference,
except of course for assignment.  The conditional x?y:z operator
is the ONLY doubtful case that is right-associative!

	So	x ? y : a ? b : c
	is	x ? y : (a ? b : c)
	not	(x ? y : a) ? b : c

Some syntactic equivalences:
	x->y	means	(*x).y
	x[y]	means	*(x+y)
	!x	means	x == 0

Rules applying to x.y and *x may thus apply to x->y or x[y] as well.
Note that "!!x" is equivalent to "x != 0".


Notes on Operators
------------------

Pointer arithmetic is always in units of the pointer's base
type.  This means that adding or subtracting an integer to or
from a pointer yields a pointer to another element in the
same array.

	p + 1 == &p [1]

Subtracting two pointers yields a distance that is also in
units of the pointer's base type.

These operators always return either 0 or 1:

	!x
	relations and equalities (<, <=, >, >=, ==, !=)
	x && y
	x || y

The logical operators (x && y, x || y) do not evaluate their
second operands if the first operand determines the result.


On two's-complement processors,
	-x == ~x + 1
	~x == -1 - x
	x & -(1<<y)	lowers x to a multiple of a power of two
	(1 << x) - y == y ^ ((1 << x) - 1)
	(x&y) + (x|y) == x + y == (x^y) + ((x&y) << 1)

Note that sizeof (type) requires parenthese, while sizeof expression
does not.



Lvalues
-------

An Lvalue represents the location of an object or function, and
might be the target of assignment.  An Rvalue is any other value,
such as an object's value or a constant or a function result.

Only these expressions are Lvalues:

	identifiers of objects and functions
	"string literal"
	(Lvalue)
	Lvalue.member
	*Rvalue

x.y is an Lvalue if x is, and has all the qualifiers of
the types of both x and y.  Casts are not Lvalues.
As a consequence of the syntactic equivalences noted above,
these expressions are also Lvalues:

	Rvalue->member
	Rvalue [Rvalue]


An Lvalue is modifiable if its type is none of these:
	function
	array
	incomplete
	const-qualified
	struct/union with any unmodifiable member


Implicit Promotions, Conversions, and Operations
------------------------------------------------

Lvalues (other than arrays and functions) become Rvalues of
unqualified type except in these contexts:
	sizeof
	&x
	x++, x--, ++x, --x
	x.member
	left sides of assignments (x=..., x+=..., etc.)

Lvalues of array type are converted to Rvalues of pointer type
pointing to their first members except in these contexts:
	sizeof
	&x
	"string literal" in a character array initializer

There are no Rvalues of array type in C outside sizeof.

Function designators are converted to Rvalues of pointer to
function type (except in &x which does that anyway).
So if "f" is the name of a function, all of these are synonyms,
and all have type "pointer to function":

	f
	*f
	***f
	************************************f

Integral promotions: Rvalues of these types (plain, signed,
and unsigned) become "int" or "unsigned int":
	char
	short
	bitfields of type int or smaller
	enum

The famous Usual Arithmetic Conversions:
Given two operands to a binary operator, find the first type
in this list that matches one of the operands, then convert
the other operand to that type.

	long double
	double
	float
	(apply integral promotion, then)
		unsigned long
		long + unsigned -> long or unsigned long
		long
		unsigned
		int

Function argument conversions in the absence of argument types:
	integral promotions
	float -> double

There is an implicit "x != 0" in

	if (x)
	while (x)
	do while (x)
	for (; x; )
	x && x
	x || x
	x ? y : z

An explicit "x != 0" in these contexts serves no semantic purpose.
And "x == 0" in these contexts might be better written as "!x".


Scopes, Namespaces, and Linkage
-------------------------------

Scopes:
	file
	block
	entire function body (for labels)
	prototype

Beware struct/union/enum tags in prototype scopes.

Distinct namespaces (per scope):
	struct/union/enum tags
	labels
	everything else

Storage classes determine linkage of names thus:

	if "static" {
		if file scope
			linkage is internal
		else
			no linkage
	} else if "extern" or a function {
		if a declaration is visible at file scope
			link to it
		else
			linkage is external
	} else if file scope
		linkage is external
	else
		no linkage

Object declarations with initializers and function declarations
with bodies are definitions.  Object declarations without
initializers are tentative definitions with zero fill if
they are not "extern".


Translation Steps
-----------------

A C compiler must behave as if each of these steps were completely
performed before proceeding.

	Turn end-of-line indicators into newlines and replace ??trigraphs
	Delete all backslash-newline pairs
	Form tokens and replace comments by single spaces
	Preprocessing and macro expansion
	Process \escape sequences in 'character constants' and "string literals"
	Delete white space, including newlines
	Concatenate adjacent "string literals"
	Parse and generate code
	Link

Posted by neodelicious
|