Skip to main content

C - Ritchie & Kernighan

In respectful memory of Dennis Ritchie, the true giant whose shoulders we have been standing on, for decades. 

Summarizing chapters as bullet points from the epic "C Programming Language" book. Good for anyone who wants to do a refresher on the C language, they dearly knew very well. Or to do a quick interview prep. 

Chapter 1-Introduction

  1. %[n]d – prints the integer in a space of 'n' characters wide,; if 'n' is not given, just prints the integer in as much space as needed
  2. %[[a][.b]]f-prints the floating point in space of width 'a' and with 'b' digits after decimal point
  3. %.0f suppresses the printing of the decimal point and the fraction part, which is zero.
  4. In C,a text stream is a sequence of characters divided into lines; each line consists of zero or more characters followed by a newline character.
  5. printf("End:%d",EOF); will print “End:-1”
  6. '\n' stands for the value of the newline character, which is 10 in ASCII
  7. white space characters are blank, tab, newline
  8. When the name of an array is used as an argument, the value passed to the function is the location or address of the beginning of the array - there is no copying of array elements
  9. Each local variable in a function comes into existence only when the function is called, and disappears when the function is exited. such variables are usually known as automatic variables
  10. An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. (the term external variable refers to a global variable)
  11. The declaration may be an explicit extern statement or may be implicit from context.If the definition of the external variable occurs in the source file before its use in a particular function, then there is no need for an extern declaration in the function.Otherwise it is needed.
  12. If the program is in several source files, and a variable is defined in file1 and used in file2 and file3, then extern declarations are needed in file2 and file3 to connect the occurrences of the variable. The usual practice is to collect extern declarations of variables and functions in a separate file, historically called a header
  13. For function names and external variables, the number of characters in the name may be less than 31, because external names may be used by assemblers and loaders over which the language has no control

Chapter2:Types,Operators and expressions


  1. Each compiler is free to choose appropriate sizes for its own hardware, subject only to
  1. Whether plain chars are signed or unsigned is machine-dependent, but printable characters are always positive.
  2. A long constant is written with a terminal l (ell) or L.Unsigned constants are written with a terminal u or U, and the suffix ul or UL indicates unsigned long.
  3. Octal and hexadecimal constants may also be followed by L to make them long and U to make them unsigned: 0XFUL is an unsigned long constant with value 15 decimal.
  4. an arbitrary byte-sized bit pattern can be specified by '\ooo' where ooo is one to three octal digits (0...7) or by '\xhh' where hh is one or more hexadecimal digits (0...9, a...f, A...F).
  5. The complete set of escape sequences 
a-alert (bell) character
\?-question mark
\'-single quote
\"-double quote
\r-carriage return
\ooo-octal number
\t-horizontal tab
\xhh-hexadecimal number
\v-vertical tab
  1. String constants can be concatenated at compile time:
"hello, " "world" is equivalent to "hello, world"
  1. The standard library function strlen(s) returns the length of its character string argument s, excluding the terminal '\0'
  2. Even character constants can be assigned to the names in a enum declaration because char constants are internally only numeric values
  3. Enumerations provide a convenient way to associate constant values with names, an alternative to #define with the advantage that the values can be generated for you
  4. If the variable in question is not automatic, the initialization is done once only, conceptionally before the program starts executing, and the initializer must be a constant expression.
  5. External and static variables are initialized to zero by default. Automatic variables for which is no explicit initializer have undefined (i.e., garbage) values.
  6. The % operator cannot be applied to a float or double.
  7. , the only automatic conversions are those that convert a ``narrower'' operand into a ``wider'' one without losing information, such as converting an integer into floating point
  8. atoi() , when provided with a string containing non-digit characters, returns the number represented by the input until the first non-digit character was encountered. Eg:atoi(12d3r) -> 12
  9. floats in an expression are not automatically converted to double;
  10. -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number.
  11. -1L < 1U, because 1U, which is an unsigned int, is promoted to a signed long.
  12. Longer integers are converted to shorter ones or to chars by dropping the excess high-order bits. Eg 512 converted to char becomes 0 since the lower byte in 512 is 0
  13. the cast produces the value of variable in the proper type; variable itself is not altered
  14. If arguments are declared by a function prototype, as the normally should be, the declaration causes automatic coercion of any arguments when the function is called. Otherwise explicit casting is needed
  15. the expression ++n increments n before its value is used, while n++ increments n after its value has been used
  16. The increment and decrement operators can only be applied to variables; applying to an expression is illegal.
  17. Right shifting an unsigned quantity always fits the vacated bits with zero. Right shifting a signed quantity will fill with bit signs (``arithmetic shift'') on some machines and with 0-bits (``logical shift'') on others.
  18. Declaring a variable as unsigned makes it work with integers as well as chars , when performing bit wise operations
  19. For a number c, c&c-1 deletes the rightmost 1 bit. Hence the number of bits set in c can be calculated using (c=c&c-1) != 0
  20. & is used to mask or set some bits to 0; | is used to set some bits to 1
  21. | using 0's and & using 1's will yield the same number . Eg: c | 0 = c&1=c; c may be a sequence of 'n' bits
  22. To extract a 'n' bit field starting from 'pos' from 'c'. Right shift 'c' by 'pos' and & with a mask having n rightmost bits as 1 and rest of the bits 0
  23. Right Rotation of 'c' (represented using 'b' bits) by 'n' places can be done as follows
            1. x=c>>n
            2. y= Number having n rightmost digits of 'c' as its 'n' leftmost digits in the same order
            3. New c=x|y
  1. A terniary expression can return any type value as one of its results. The returned result values may also be of different types
    () [] -> .
    left to right
    ! ~ ++ -- + - * (type) sizeof
    right to left
    * / %
    left to right
    + -
    left to right
    << >>
    left to right
    < <= > >=
    left to right
    == !=
    left to right
    left to right
    left to right
    left to right
    left to right
    left to right
    right to left
    = += -= *= /= %= &= ^= |= <<= >>=
    right to left
    left to right

    1. Function calls, nested assignment statements, and increment and decrement operators cause ``side effects'' - some variable is changed as a by-product of the evaluation of an expression
    2. the order in which function arguments and the operands of operators are evaluated is not specified. So varyng results under various compilers
    3. In unix, while evaluating 'f() <op> g()' , f() is evaluated before g(). arguments are evaluated from right to left.Eg: g(++i,i++) call is resolved into g(i+2,i)

      To be continued ....


Popular posts from this blog

Learning Spark Streaming #1

I have been doing a lot of Spark in the past few months, and of late, have taken a keen interest in Spark Streaming . In a series of posts, I intend to cover a lot of details about Spark streaming and even other stream processing systems in general, either presenting technical arguments/critiques, with any micro benchmarks as needed. Some high level description of Spark Streaming (as of 1.4),  most of which you can find in the programming guide .  At a high level, Spark streaming is simply a spark job run on very small increments of input data (i.e micro batch), every 't' seconds, where t can be as low as 1 second. As with any stream processing system, there are three big aspects to the framework itself. Ingesting the data streams : This is accomplished via DStreams, which you can think of effectively as a thin wrapper around an input source such as Kafka/HDFS which knows how to read the next N entries from the input. The receiver based approach is a little compl

Setting up Hadoop/YARN/Spark/Hive on Mac OSX El Capitan

If you are like me, who loves to have everything you are developing against working locally in a mini-integration environment, read on Here, we attempt to get some pretty heavy-weight stuff working locally on your mac, namely Hadoop (Hadoop2/HDFS) YARN (So you can submit MR jobs) Spark (We will illustrate with Spark Shell, but should work on YARN mode as well) Hive (So we can create some tables and play with it)  We will use the latest stable Cloudera distribution, and work off the jars. Most of the methodology is borrowed from here , we just link the four pieces together nicely in this blog.  Download Stuff First off all, make sure you have Java 7/8 installed, with JAVA_HOME variable setup to point to the correct location. You have to download the CDH tarballs for Hadoop, Zookeeper, Hive from the tarball page (CDH 5.4.x page ) and untar them under a folder (refered to as CDH_HOME going forward) as hadoop, zookeeper $ ls $HOME /bin/cdh/5.4.7 hadoop

HDFS Client Configs for talking to HA Hadoop NameNodes

One more simple thing, that had relatively scarce documentation out on the Internet. As you might know, Hadoop NameNodes finally became HA in 2.0 . The HDFS client configuration, which is already a little bit tedious, became more complicated. Traditionally, there were two ways to configure a HDFS client (lets stick to Java) Copy over the entire Hadoop config directory with all the xml files, place it somewhere in the classpath of your app or construct a Hadoop Configuration object by manually adding in those files. Simply provide the HDFS NameNode URI and let the client do the rest.          Configuration conf = new Configuration(false);         conf.set("", "hdfs://localhost:8020"); // this is deprecated now         conf.set("fs.defaultFS", "hdfs://localhost:8020");         FileSystem fs = FileSystem.get(conf); Most people prefer 2, unless you need way more configs from the actual xml config files, at which po