-
07-10-2014
#1
Registered User
error: syntax error before printf
Hi. I have just learnt C programming and I don;t know what’s wrong with the printf(«Your BMI is %0.2f.n», BMI);below. Is there anyone can check it for me please?
Code:
/* Demonstates variables and constants*/ #include <stdio.h> /*Declare the need variable*/ float BMI; int height_in_meters, weight_in_killograms; int main() { /* Input data from user*/ printf("How tall are you in meters:"); scanf("d%", &height_in_meters); printf("Please enter your weight in killograms:"); scanf("d%", &weight_in_killograms); /* Perform conversions*/ BMI = (weight_in_killograms)/(height_in_meters)^2 /* Display result on the screen*/ printf("Your BMI is %0.2f.n", BMI); return 0; }
-
07-11-2014
#2
Registered User
There is nothing wrong with that line. However, there are several other problems in the code that your compiler should be warning you about. If you haven’t already, you should compile with maximum warnings (see your compiler documentation for how to do this).
This is what I got when I compiled your code:
Code:
/* main.c||In function 'main':| main.c|17|warning: spurious trailing '%' in format| main.c|17|warning: too many arguments for format| main.c|19|warning: spurious trailing '%' in format| main.c|19|warning: too many arguments for format| main.c|27|error: expected ';' before 'printf'| ||=== Build finished: 1 errors, 4 warnings ===| */
See if you can use these warnings to figure out where your problems are.
Also note that there is no exponent operator in ‘C’ — so ‘^’ does not do what you think it does (it is the bitwise XOR operator). For smaller powers, you’d be better off just doing repeated multiplication.
-
07-11-2014
#3
Hurry Slowly
also deviding integers will result in integer part only… And how do you plan to store people height in meters as integer?
In your world only leave people of 1 and 2 meter height?
All problems in computer science can be solved by another level of indirection,
except for the problem of too many layers of indirection.
� David J. Wheeler
-
07-11-2014
#4
Registered User
I have already correct some of the mistakes here, but I don’t know why it still doesn’t work.
Code:
/* Demonstates variables and constants*/ #include <stdio.h> /*Declare the need variable*/ float height_in_meters, weight_in_killograms, BMI; int main() { /* Input data from user*/ printf("How tall are you in meters:"); scanf("d%", &height_in_meters); printf("Please enter your weight in killograms:"); scanf("d%", &weight_in_killograms); /* Perform conversions*/ BMI = height_in_meters*height_in_meters/weight_in_killograms; /* Display result on the screen*/ printf("Your BMI is %0.2f.n", BMI); return 0; }
When I try to run the program, there are some of the mistakes like below:
How tall are you in meters:6.1
Please enter your weight in killograms:Your BMI is -1.#J.
Press any key to continue . . .
-
07-11-2014
#5
Registered User
All right. I am sorry. I have already corrected the mistake here. Thanks for your help.
[code]
/* Demonstates variables and constants*/
#include <stdio.h>/*Declare the need variable*/
float height_in_meters, weight_in_killograms, BMI;int main()
{/* Input data from user*/
printf(«How tall are you in meters:»);
scanf(«%f», &height_in_meters);
printf(«Please enter your weight in killograms:»);
scanf(«%f», &weight_in_killograms);/* Perform conversions*/
BMI = weight_in_killograms/(height_in_meters*height_in_meters);
/* Display result on the screen*/
printf(«Your BMI is %0.2f.n», BMI);
return 0;
[code]
-
07-12-2014
#6
Registered User
You should also stop using global variables, this is very bad practice and since everything is in main() you don’t even need the global.
Jim
-
07-12-2014
#7
Registered User
Are you dyslectic?
«%d» and «d%» are NOT the same in C.
Tim S.
«…a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match..» Bill Bryson
Improve Article
Save Article
Improve Article
Save Article
Error is an illegal operation performed by the user which results in abnormal working of the program.
Programming errors often remain undetected until the program is compiled or executed. Some of the errors inhibit the program from getting compiled or executed. Thus errors should be removed before compiling and executing.
The most common errors can be broadly classified as follows.
Type of errors:
- Syntax errors: Errors that occur when you violate the rules of writing C/C++ syntax are known as syntax errors. This compiler error indicates something that must be fixed before the code can be compiled. All these errors are detected by compiler and thus are known as compile-time errors.
Most frequent syntax errors are:- Missing Parenthesis (})
- Printing the value of variable without declaring it
- Missing semicolon like this:
C++
#include <iostream>
using
namespace
std;
void
main()
{
int
x = 10;
int
y = 15;
cout <<
" "
<< (x, y)
}
C
#include<stdio.h>
void
main()
{
int
x = 10;
int
y = 15;
printf
(
"%d"
, (x, y))
}
Error:
error: expected ';' before '}' token
- Syntax of a basic construct is written wrong. For example : while loop
C++
#include <iostream>
using
namespace
std;
int
main(
void
)
{
while
(.)
{
cout <<
"hello"
;
}
return
0;
}
C
#include<stdio.h>
int
main(
void
)
{
while
(.)
{
printf
(
"hello"
);
}
return
0;
}
Error:
error: expected expression before '.' token while(.)
- In the given example, the syntax of while loop is incorrect. This causes a syntax error.
- Run-time Errors : Errors which occur during program execution(run-time) after successful compilation are called run-time errors. One of the most common run-time error is division by zero also known as Division error. These types of error are hard to find as the compiler doesn’t point to the line at which the error occurs.
For more understanding run the example given below.
C++
#include <iostream>
#include <bits/stdc++.h>
using
namespace
std;
void
main()
{
int
n = 9,
div
= 0;
div
= n/0;
cout <<
"result = "
<<
div
;
}
C
#include<stdio.h>
void
main()
{
int
n = 9,
div
= 0;
div
= n/0;
printf
(
"result = %d"
,
div
);
}
Error:
warning: division by zero [-Wdiv-by-zero] div = n/0;
- In the given example, there is Division by zero error. This is an example of run-time error i.e errors occurring while running the program.
- Linker Errors: These error occurs when after compilation we link the different object files with main’s object using Ctrl+F9 key(RUN). These are errors generated when the executable of the program cannot be generated. This may be due to wrong function prototyping, incorrect header files. One of the most common linker error is writing Main() instead of main().
C++
#include <bits/stdc++.h>
using
namespace
std;
void
Main()
{
int
a = 10;
cout <<
" "
<< a;
}
C
#include<stdio.h>
void
Main()
{
int
a = 10;
printf
(
"%d"
, a);
}
Error:
(.text+0x20): undefined reference to `main'
- Logical Errors : On compilation and execution of a program, desired output is not obtained when certain input values are given. These types of errors which provide incorrect output but appears to be error free are called logical errors. These are one of the most common errors done by beginners of programming.
These errors solely depend on the logical thinking of the programmer and are easy to detect if we follow the line of execution and determine why the program takes that path of execution.
C++
int
main()
{
int
i = 0;
for
(i = 0; i < 3; i++);
{
cout <<
"loop "
;
continue
;
}
return
0;
}
C
int
main()
{
int
i = 0;
for
(i = 0; i < 3; i++);
{
printf
(
"loop "
);
continue
;
}
getchar
();
return
0;
}
- No output
- Semantic errors : This error occurs when the statements written in the program are not meaningful to the compiler.
C++
int
main()
{
int
a, b, c;
a + b = c;
}
C
void
main()
{
int
a, b, c;
a + b = c;
}
Error:
error: lvalue required as left operand of assignment a + b = c; //semantic error
This article is contributed by Krishna Bhatia. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Defined in header |
||
(1) | ||
int printf( const char *format, … ); |
(until C99) | |
int printf( const char *restrict format, … ); |
(since C99) | |
(2) | ||
int fprintf( FILE *stream, const char *format, … ); |
(until C99) | |
int fprintf( FILE *restrict stream, const char *restrict format, … ); |
(since C99) | |
(3) | ||
int sprintf( char *buffer, const char *format, … ); |
(until C99) | |
int sprintf( char *restrict buffer, const char *restrict format, … ); |
(since C99) | |
int snprintf( char *restrict buffer, size_t bufsz, |
(4) | (since C99) |
int printf_s( const char *restrict format, … ); |
(5) | (since C11) |
int fprintf_s( FILE *restrict stream, const char *restrict format, … ); |
(6) | (since C11) |
int sprintf_s( char *restrict buffer, rsize_t bufsz, |
(7) | (since C11) |
int snprintf_s( char *restrict buffer, rsize_t bufsz, |
(8) | (since C11) |
Loads the data from the given locations, converts them to character string equivalents and writes the results to a variety of sinks/streams:
1) Writes the results to the output stream stdout.
2) Writes the results to the output stream stream
.
3) Writes the results to a character string buffer
. The behavior is undefined if the string to be written (plus the terminating null character) exceeds the size of the array pointed to by buffer
.
4) Writes the results to a character string buffer
. At most bufsz
— 1 characters are written. The resulting character string will be terminated with a null character, unless bufsz
is zero. If bufsz
is zero, nothing is written and buffer
may be a null pointer, however the return value (number of bytes that would be written not including the null terminator) is still calculated and returned.
5-8) Same as (1-4), except that the following errors are detected at runtime and call the currently installed constraint handler function:
-
- the conversion specifier
%n
is present informat
- any of the arguments corresponding to
%s
is a null pointer -
stream
orformat
orbuffer
is a null pointer -
bufsz
is zero or greater than RSIZE_MAX - encoding errors occur in any of string and character conversion specifiers
- (for
sprintf_s
only), the string to be stored inbuffer
(including the trailing null) would be exceedbufsz
- the conversion specifier
- As with all bounds-checked functions,
printf_s
,fprintf_s
,sprintf_s
, andsnprintf_s
are only guaranteed to be available if __STDC_LIB_EXT1__ is defined by the implementation and if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including <stdio.h>.
[edit] Parameters
stream | — | output file stream to write to |
buffer | — | pointer to a character string to write to |
bufsz | — | up to bufsz — 1 characters may be written, plus the null terminator |
format | — | pointer to a null-terminated byte string specifying how to interpret the data |
… | — | arguments specifying data to print. If any argument after default argument promotions is not the type expected by the corresponding conversion specifier, or if there are fewer arguments than required by format , the behavior is undefined. If there are more arguments than required by format , the extraneous arguments are evaluated and ignored.
|
The format string consists of ordinary byte characters (except %
), which are copied unchanged into the output stream, and conversion specifications. Each conversion specification has the following format:
-
- introductory
%
character
- introductory
-
- (optional) one or more flags that modify the behavior of the conversion:
-
-
-
: the result of the conversion is left-justified within the field (by default it is right-justified) -
+
: the sign of signed conversions is always prepended to the result of the conversion (by default the result is preceded by minus only when it is negative) - space: if the result of a signed conversion does not start with a sign character, or is empty, space is prepended to the result. It is ignored if
+
flag is present. -
#
: alternative form of the conversion is performed. See the table below for exact effects otherwise the behavior is undefined. -
0
: for integer and floating point number conversions, leading zeros are used to pad the field instead of space characters. For integer numbers it is ignored if the precision is explicitly specified. For other conversions using this flag results in undefined behavior. It is ignored if-
flag is present.
-
-
- (optional) integer value or
*
that specifies minimum field width. The result is padded with space characters (by default), if required, on the left when right-justified, or on the right if left-justified. In the case when*
is used, the width is specified by an additional argument of type int, which appears before the argument to be converted and the argument supplying precision if one is supplied. If the value of the argument is negative, it results with the-
flag specified and positive field width. (Note: This is the minimum width: The value is never truncated.)
- (optional) integer value or
-
- (optional)
.
followed by integer number or*
, or neither that specifies precision of the conversion. In the case when*
is used, the precision is specified by an additional argument of type int, which appears before the argument to be converted, but after the argument supplying minimum field width if one is supplied. If the value of this argument is negative, it is ignored. If neither a number nor*
is used, the precision is taken as zero. See the table below for exact effects of precision.
- (optional)
-
- (optional) length modifier that specifies the size of the argument (in combination with the conversion format specifier, it specifies the type of the corresponding argument)
-
- conversion format specifier
The following format specifiers are available:
Conversion Specifier |
Explanation | Expected Argument Type |
||||||||
---|---|---|---|---|---|---|---|---|---|---|
Length → |
hh
(C99) |
h
|
(none) | l
|
ll
(C99) |
j
(C99) |
z
(C99) |
t
(C99) |
L
|
|
%
|
writes literal % . The full conversion specification must be %% .
|
N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
c
|
The argument is first converted to unsigned char. |
N/A | N/A |
int |
wint_t |
N/A | N/A | N/A | N/A | N/A |
s
|
The argument must be a pointer to the initial element of an array of characters. |
N/A | N/A |
char* |
wchar_t* |
N/A | N/A | N/A | N/A | N/A |
d i
|
Precision specifies the minimum number of digits to appear. The default precision is 1. If both the converted value and the precision are 0 the conversion results in no characters. |
signed char |
short |
int |
long |
long long |
intmax_t |
signed size_t |
ptrdiff_t |
N/A |
o
|
Precision specifies the minimum number of digits to appear. The default precision is 1. |
unsigned char |
unsigned short |
unsigned int |
unsigned long |
unsigned long long |
uintmax_t |
size_t |
unsigned version of ptrdiff_t |
N/A |
x X
|
For the |
N/A | ||||||||
u
|
Precision specifies the minimum number of digits to appear. |
N/A | ||||||||
f F
|
Precision specifies the exact number of digits to appear after the decimal point character. |
N/A | N/A |
double |
double (C99) |
N/A | N/A | N/A | N/A |
long double |
e E
|
For the |
N/A | N/A | N/A | N/A | N/A | N/A | |||
a A
(C99) |
For the |
N/A | N/A | N/A | N/A | N/A | N/A | |||
g G
|
For the
Unless alternative representation is requested the trailing zeros are removed, also the decimal point character is removed if no fractional part is left. |
N/A | N/A | N/A | N/A | N/A | N/A | |||
n
|
The result is written to the value pointed to by the argument. |
signed char* |
short* |
int* |
long* |
long long* |
intmax_t* |
signed size_t* |
ptrdiff_t* |
N/A |
p
|
writes an implementation defined character sequence defining a pointer. | N/A | N/A | void* | N/A | N/A | N/A | N/A | N/A | N/A |
The floating point conversion functions convert infinity to inf
or infinity
. Which one is used is implementation defined.
Not-a-number is converted to nan
or nan(char_sequence)
. Which one is used is implementation defined.
The conversions F
, E
, G
, A
output INF
, INFINITY
, NAN
instead.
Even though %c
expects int
argument, it is safe to pass a char
because of the integer promotion that takes place when a variadic function is called.
The correct conversion specifications for the fixed-width character types (int8_t, etc) are defined in the header <inttypes.h>
(although PRIdMAX, PRIuMAX, etc is synonymous with %jd
, %ju
, etc).
The memory-writing conversion specifier %n is a common target of security exploits where format strings depend on user input and is not supported by the bounds-checked printf_s
family of functions.
There is a sequence point after the action of each conversion specifier; this permits storing multiple %n results in the same variable or, as an edge case, printing a string modified by an earlier %n within the same call.
If a conversion specification is invalid, the behavior is undefined.
[edit] Return value
1,2) number of characters transmitted to the output stream or negative value if an output error or an encoding error (for string and character conversion specifiers) occurred
3) number of characters written to buffer
(not counting the terminating null character), or a negative value if an encoding error (for string and character conversion specifiers) occurred
4) number of characters (not including the terminating null character) which would have been written to buffer
if bufsz
was ignored, or a negative value if an encoding error (for string and character conversion specifiers) occurred
5,6) number of characters transmitted to the output stream or negative value if an output error, a runtime constraints violation error, or an encoding error occurred.
7) number of characters written to buffer
, not counting the null character (which is always written as long as buffer
is not a null pointer and bufsz
is not zero and not greater than RSIZE_MAX
), or zero on runtime constraint violations, and negative value on encoding errors
number of characters not including the terminating null character (which is always written as long as
buffer
is not a null pointer and bufsz
is not zero and not greater than RSIZE_MAX
), which would have been written to buffer
if bufsz
was ignored, or a negative value if a runtime constraints violation or an encoding error occurred
[edit] Notes
The C standard and POSIX specify that the behavior of sprintf
and its variants is undefined when an argument overlaps with the destination buffer. Example:
sprintf(dst, "%s and %s", dst, t); // <- broken: undefined behavior
POSIX specifies that errno is set on error. It also specifies additional conversion specifications, most notably support for argument reordering (n$ immediately after % indicates n
‘th argument).
Calling snprintf
with zero bufsz
and null pointer for buffer
is useful to determine the necessary buffer size to contain the output:
const char fmt[] = "sqrt(2) = %f"; int sz = snprintf(NULL, 0, fmt, sqrt(2)); char buf[sz + 1]; // note +1 for terminating null byte snprintf(buf, sizeof buf, fmt, sqrt(2));
snprintf_s
, just like snprintf
, but unlike sprintf_s
, will truncate the output to fit in bufsz-1
.
[edit] Example
#include <stdio.h> #include <stdint.h> #include <inttypes.h> int main(void) { const char* s = "Hello"; printf("Strings:n"); // same as puts("Strings"); printf(" padding:n"); printf("t[%10s]n", s); printf("t[%-10s]n", s); printf("t[%*s]n", 10, s); printf(" truncating:n"); printf("t%.4sn", s); printf("t%.*sn", 3, s); printf("Characters:t%c %%n", 'A'); printf("Integers:n"); printf("tDecimal:t%i %d %.6i %i %.0i %+i %in", 1, 2, 3, 0, 0, 4,-4); printf("tHexadecimal:t%x %x %X %#xn", 5, 10, 10, 6); printf("tOctal:tt%o %#o %#on", 10, 10, 4); printf("Floating point:n"); printf("tRounding:t%f %.0f %.32fn", 1.5, 1.5, 1.3); printf("tPadding:t%05.2f %.2f %5.2fn", 1.5, 1.5, 1.5); printf("tScientific:t%E %en", 1.5, 1.5); printf("tHexadecimal:t%a %An", 1.5, 1.5); printf("tSpecial values:t0/0=%g 1/0=%gn", 0.0/0.0, 1.0/0.0); printf("Fixed-width types:n"); printf("tLargest 32-bit value is %" PRIu32 " or %#" PRIx32 "n", UINT32_MAX, UINT32_MAX ); }
Possible output:
Strings: padding: [ Hello] [Hello ] [ Hello] truncating: Hell Hel Characters: A % Integers: Decimal: 1 2 000003 0 +4 -4 Hexadecimal: 5 a A 0x6 Octal: 12 012 04 Floating point: Rounding: 1.500000 2 1.30000000000000004440892098500626 Padding: 01.50 1.50 1.50 Scientific: 1.500000E+00 1.500000e+00 Hexadecimal: 0x1.8p+0 0X1.8P+0 Special values: 0/0=-nan 1/0=inf Fixed-width types: Largest 32-bit value is 4294967295 or 0xffffffff
[edit] References
- C17 standard (ISO/IEC 9899:2018):
-
- 7.21.6.1 The fprintf function (p: 225-230)
-
- 7.21.6.3 The printf function (p: 236)
-
- 7.21.6.5 The snprintf function (p: 237)
-
- 7.21.6.6 The sprintf function (p: 237)
-
- K.3.5.3.1 The fprintf_s function (p: 430)
-
- K.3.5.3.3 The printf_s function (p: 432)
-
- K.3.5.3.5 The snprintf_s function (p: 432-433)
-
- K.3.5.3.6 The sprintf_s function (p: 433)
- C11 standard (ISO/IEC 9899:2011):
-
- 7.21.6.1 The fprintf function (p: 309-316)
-
- 7.21.6.3 The printf function (p: 324)
-
- 7.21.6.5 The snprintf function (p: 325)
-
- 7.21.6.6 The sprintf function (p: 325-326)
-
- K.3.5.3.1 The fprintf_s function (p: 591)
-
- K.3.5.3.3 The printf_s function (p: 593-594)
-
- K.3.5.3.5 The snprintf_s function (p: 594-595)
-
- K.3.5.3.6 The sprintf_s function (p: 595-596)
- C99 standard (ISO/IEC 9899:1999):
-
- 7.19.6.1 The fprintf function (p: 274-282)
-
- 7.19.6.3 The printf function (p: 290)
-
- 7.19.6.5 The snprintf function (p: 290-291)
-
- 7.19.6.6 The sprintf function (p: 291)
- C89/C90 standard (ISO/IEC 9899:1990):
-
- 4.9.6.1 The fprintf function
-
- 4.9.6.3 The printf function
-
- 4.9.6.5 The sprintf function
[edit] See also
Types of Errors in C
Overview
An error in the C language is an issue that arises in a program, making the program not work in the way it was supposed to work or may stop it from compiling as well.
If an error appears in a program, the program can do one of the following three things: the code will not compile, the program will stop working during execution, or the program will generate garbage values or incorrect output. There are five different types of errors in C Programming like Syntax Error, Run Time Error, Logical Error, Semantic Error, and Linker Error.
Scope
- This article explains errors and their types in C Programming Language.
- This article covers the explanation and examples for each type of error in C Programming Language (syntax error, run time error, logical error, semantic error, linker error).
Introduction
Let us say you want to create a program that prints today’s date. But instead of writing printf in the code, you wrote print. Because of this, our program will generate an error as the compiler would not understand what the word print means. Hence, today’s date will not print. This is what we call an error. An error is a fault or problem in a program that leads to abnormal behavior of the program. In other words, an error is a situation in which the program does something which it was not supposed to do. This includes producing incorrect or unexpected output, stopping a program that was running, or hindering the code’s compilation. Therefore it is important to remove all errors from our code, this is known as debugging.
How to Read an Error in C?
In order to resolve an error, we must figure out how and why did the error occur. Whenever we encounter an error in our code, the compiler stops the code compilation if it is a syntax error or it either stops the program’s execution or generates a garbage value if it is a run time error.
Syntax errors are easy to figure out because the compiler highlights the line of code that caused the error. Generally, we can find the error’s root cause on the highlighted line or above the highlighted line.
For example:
#include <stdio.h> int main() { int var = 10 return 0; }
Output:
error: expected ',' or ';' before 'return' 4 | return 0;
As we can see, the compiler shows an error on line 4 of the code. So, in order to figure out the problem, we will go through line 4 and a few lines above it. Once we do that, we can quickly determine that we are missing a semi-colon (;) in line 4. The compiler also suggested the same thing.
Other than the syntax errors, run time errors are often encountered while coding. These errors are the ones that occur while the code is being executed.
Let us now see an example of a run time error:
#include<stdio.h> void main() { int var; var = 20 / 0; printf("%d", var); }
Output:
warning: division by zero [-Wdiv-by-zero] 6 | var = 20 / 0;
As we can see, the compiler generated a warning at line 6 because we are dividing a number by zero.
Sometimes, the compiler does not throw a run time error. Instead, it returns a garbage value. In situations like these, we have to figure out why did we get an incorrect output by comparing the output with the expected output. In other cases, the compiler does not display any error at all. The program execution just ends abruptly in cases like these.
Let us take another example to understand this kind of run time error:
#include <stdio.h> #include <stdlib.h> int main() { int arr[1]; arr[0] = 10; int val = arr[10000]; printf("%d", val); return 0; }
Output:
In the above code, we are trying to access the 10000th element but the size of array is only 1 therefore there is no space allocated to the 10000th element, this is known as segmentation fault.
Types of Errors in C
There are five different types of errors in C.
- Syntax Error
- Run Time Error
- Logical Error
- Semantic Error
- Linker Error
1. Syntax Error
Syntax errors occur when a programmer makes mistakes in typing the code’s syntax correctly or makes typos. In other words, syntax errors occur when a programmer does not follow the set of rules defined for the syntax of C language.
Syntax errors are sometimes also called compilation errors because they are always detected by the compiler. Generally, these errors can be easily identified and rectified by programmers.
The most commonly occurring syntax errors in C language are:
- Missing semi-colon (;)
- Missing parenthesis ({})
- Assigning value to a variable without declaring it
Let us take an example to understand syntax errors:
#include <stdio.h> void main() { var = 5; // we did not declare the data type of variable printf("The variable is: %d", var); }
Output:
error: 'var' undeclared (first use in this function)
If the user assigns any value to a variable without defining the data type of the variable, the compiler throws a syntax error.
Let’s see another example:
#include <stdio.h> void main() { for (int i = 0;) { // incorrect syntax of the for loop printf("Scaler Academy"); } }
Output:
error: expected expression before ')' token
A for loop needs 3 arguments to run. Since we entered only one argument, the compiler threw a syntax error.
2. Runtime Error
Errors that occur during the execution (or running) of a program are called RunTime Errors. These errors occur after the program has been compiled successfully. When a program is running, and it is not able to perform any particular operation, it means that we have encountered a run time error. For example, while a certain program is running, if it encounters the square root of -1 in the code, the program will not be able to generate an output because calculating the square root of -1 is not possible. Hence, the program will produce an error.
Runtime errors can be a little tricky to identify because the compiler can not detect these errors. They can only be identified once the program is running. Some of the most common run time errors are: number not divisible by zero, array index out of bounds, string index out of bounds, etc.
Runtime errors can occur because of various reasons. Some of the reasons are:
- Mistakes in the Code: Let us say during the execution of a while loop, the programmer forgets to enter a break statement. This will lead the program to run infinite times, hence resulting in a run time error.
- Memory Leaks: If a programmer creates an array in the heap but forgets to delete the array’s data, the program might start leaking memory, resulting in a run time error.
- Mathematically Incorrect Operations: Dividing a number by zero, or calculating the square root of -1 will also result in a run time error.
- Undefined Variables: If a programmer forgets to define a variable in the code, the program will generate a run time error.
Example 1:
// A program that calculates the square root of integers #include <stdio.h> #include <math.h> int main() { for (int i = 4; i >= -2; i--) { printf("%f", sqrt(i)); printf("n"); } return 0; }
Output:
2.000000 1.732051 1.414214 1.000000 0.000000 -1.#IND00 -1.#IND00
**In some compilers, you may also see this output: **
2.000000 1.732051 1.414214 1.000000 0.000000 -nan -nan
In the above example, we used a for loop to calculate the square root of six integers. But because we also tried calculating the square root of two negative numbers, the program generated two errors (the IND written above stands for «Indeterminate»). These errors are the run time errors.
-nan is similar to IND.Example 2:
#include<stdio.h> void main() { int var = 2147483649; printf("%d", var); }
Output:
This is an integer overflow error. The maximum value an integer can hold in C is 2147483647. Since in the above example, we assigned 2147483649 to the variable var, the variable overflows, and we get -2147483647 as the output (because of the circular property).
3. Logical Error
Sometimes, we do not get the output we expected after the compilation and execution of a program. Even though the code seems error free, the output generated is different from the expected one. These types of errors are called Logical Errors. Logical errors are those errors in which we think that our code is correct, the code compiles without any error and gives no error while it is running, but the output we get is different from the output we expected.
In 1999, NASA lost a spacecraft due to a logical error. This happened because of some miscalculations between the English and the American Units. The software was coded to work for one system but was used with the other.
For Example:
#include <stdio.h> void main() { float a = 10; float b = 5; if (b = 0) { // we wrote = instead of == printf("Division by zero is not possible"); } else { printf("The output is: %f", a/b); } }
Output:
INF signifies a division by zero error. In the above example, at line 8, we wanted to check whether the variable b was equal to zero. But instead of using the equal to comparison operator (==), we use the assignment operator (=). Because of this, the if statement became false and the value of b became 0. Finally, the else clause got executed.
4. Semantic Error
Errors that occur because the compiler is unable to understand the written code are called Semantic Errors. A semantic error will be generated if the code makes no sense to the compiler, even though it is syntactically correct. It is like using the wrong word in the wrong place in the English language. For example, adding a string to an integer will generate a semantic error.
Semantic errors are different from syntax errors, as syntax errors signify that the structure of a program is incorrect without considering its meaning. On the other hand, semantic errors signify the incorrect implementation of a program by considering the meaning of the program.
The most commonly occurring semantic errors are: use of un-initialized variables, type compatibility, and array index out of bounds.
Example 1:
#include <stdio.h> void main() { int a, b, c; a * b = c; // This will generate a semantic error }
Output:
error: lvalue required as left operand of assignment
When we have an expression on the left-hand side of an assignment operator (=), the program generates a semantic error. Even though the code is syntactically correct, the compiler does not understand the code.
Example 2:
#include <stdio.h> void main() { int arr[5] = {5, 10, 15, 20, 25}; int arraySize = sizeof(arr)/sizeof(arr[0]); for (int i = 0; i <= arraySize; i++) { printf("%d n", arr[i]); } }
Output:
In the above example, we printed six elements while the array arr only had five. Because we tried to access the sixth element of the array, we got a semantic error and hence, the program generated a garbage value.
5. Linker Error
Linker is a program that takes the object files generated by the compiler and combines them into a single executable file. Linker errors are the errors encountered when the executable file of the code can not be generated even though the code gets compiled successfully. This error is generated when a different object file is unable to link with the main object file. We can run into a linked error if we have imported an incorrect header file in the code, we have a wrong function declaration, etc.
For Example:
#include <stdio.h> void Main() { int var = 10; printf("%d", var); }
Output:
undefined reference to `main'
In the above code, as we wrote Main() instead of main(), the program generated a linker error. This happens because every file in the C language must have a main() function. As in the above program, we did not have a main() function, the program was unable to run the code, and we got an error. This is one of the most common type of linker error.
Conclusion
- There are 5 different types of errors in C programming language: Syntax error, Runtime error, Logical error, Semantic error, and Linker error.
- Syntax errors, linker errors, and semantic errors can be identified by the compiler during compilation. Logical errors and run time errors are encountered after the program is compiled and executed.
- Syntax errors, linker errors, and semantic errors are relatively easy to identify and rectify compared to the logical and run time errors. This is so because the compiler generates these 3 (syntax, linker, semantic) errors during compilation itself, while the other 2 errors are generated during or after the execution.
An example of the printf function
The printf format string is a control parameter used by a class of functions in the input/output libraries of C and many other programming languages. The string is written in a simple template language: characters are usually copied literally into the function’s output, but format specifiers, which start with a %
character, indicate the location and method to translate a piece of data (such as a number) to characters.
«printf» is the name of one of the main C output functions, and stands for «print formatted». printf format strings are complementary to scanf format strings, which provide formatted input (lexing aka. parsing). In both cases these provide simple functionality and fixed format compared to more sophisticated and flexible template engines or lexers/parsers, but are sufficient for many purposes.
Many languages other than C copy the printf format string syntax closely or exactly in their own I/O functions.
Mismatches between the format specifiers and type of the data can cause crashes and other vulnerabilities. The format string itself is very often a string literal, which allows static analysis of the function call. However, it can also be the value of a variable, which allows for dynamic formatting but also a security vulnerability known as an uncontrolled format string exploit.
History[edit]
Early programming languages such as Fortran used special statements with completely different syntax from other calculations to build formatting descriptions. In this example, the format is specified on line 601, and the WRITE command refers to it by line number:
WRITE OUTPUT TAPE 6, 601, IA, IB, IC, AREA 601 FORMAT (4H A= ,I5,5H B= ,I5,5H C= ,I5, & 8H AREA= ,F10.2, 13H SQUARE UNITS)
ALGOL 68 had more function-like API, but still used special syntax (the $
delimiters surround special formatting syntax):
printf(($"Color "g", number1 "6d,", number2 "4zd,", hex "16r2d,", float "-d.2d,", unsigned value"-3d"."l$, "red", 123456, 89, BIN 255, 3.14, 250));
But using the normal function calls and data types simplifies the language and compiler, and allows the implementation of the input/output to be written in the same language. These advantages outweigh the disadvantages (such as a complete lack of type safety in many instances) and in most newer languages I/O is not part of the syntax.
C’s printf
has its origins in BCPL’s writef
function (1966). In comparison to C
and printf
, *N
is a BCPL language escape sequence representing a newline character (for which C uses the escape sequence n
) and the order of the format specification’s field width and type is reversed in writef
:[1]
WRITEF("%I2-QUEENS PROBLEM HAS %I5 SOLUTIONS*N", NUMQUEENS, COUNT)
Probably the first copying of the syntax outside the C language was the Unix printf
shell command, which first appeared in Version 4, as part of the port to C.[2]
Format placeholder specification[edit]
Formatting takes place via placeholders within the format string. For example, if a program wanted to print out a person’s age, it could present the output by prefixing it with «Your age is «, and using the signed decimal specifier character d
to denote that we want the integer for the age to be shown immediately after that message, we may use the format string:
printf("Your age is %d", age);
Syntax[edit]
The syntax for a format placeholder is
%[parameter][flags][width][.precision][length]type
Parameter field[edit]
This is a POSIX extension and not in C99. The Parameter field can be omitted or can be:
Character | Description |
---|---|
n$ | n is the number of the parameter to display using this format specifier, allowing the parameters provided to be output multiple times, using varying format specifiers or in different orders. If any single placeholder specifies a parameter, all the rest of the placeholders MUST also specify a parameter. For example, printf("%2$d %2$#x; %1$d %1$#x",16,17) produces 17 0x11; 16 0x10 .
|
This feature mainly sees its use in localization, where the order of occurrence of parameters vary due to the language-dependent convention.
On the non-POSIX Microsoft Windows, support for this feature is placed in a separate printf_p function.
Flags field[edit]
The Flags field can be zero or more (in any order) of:
Character | Description |
---|---|
— (minus) |
Left-align the output of this placeholder. (The default is to right-align the output.) |
+ (plus) |
Prepends a plus for positive signed-numeric types. positive = +, negative = —. (The default doesn’t prepend anything in front of positive numbers.) |
(space) |
Prepends a space for positive signed-numeric types. positive = , negative = —. This flag is ignored if the + flag exists.(The default doesn’t prepend anything in front of positive numbers.) |
0 (zero) |
When the ‘width’ option is specified, prepends zeros for numeric types. (The default prepends spaces.) For example, printf("%4X",3) produces 3 , while printf("%04X",3) produces 0003 .
|
‘ (apostrophe) |
The integer or exponent of a decimal has the thousands grouping separator applied. |
# (hash) |
Alternate form: For g and G types, trailing zeros are not removed. For f, F, e, E, g, G types, the output always contains a decimal point. For o, x, X types, the text 0, 0x, 0X, respectively, is prepended to non-zero numbers. |
Width field[edit]
The Width field specifies a minimum number of characters to output and is typically used to pad fixed-width fields in tabulated output, where the fields would otherwise be smaller, although it does not cause truncation of oversized fields.
The width field may be omitted, or a numeric integer value, or a dynamic value when passed as another argument when indicated by an asterisk *
.[3] For example, printf("%*d", 5, 10)
will result in 10
being printed, with a total width of 5 characters.
Though not part of the width field, a leading zero is interpreted as the zero-padding flag mentioned above, and a negative value is treated as the positive value in conjunction with the left-alignment -
flag also mentioned above.
Precision field[edit]
The Precision field usually specifies a maximum limit on the output, depending on the particular formatting type. For floating-point numeric types, it specifies the number of digits to the right of the decimal point that the output should be rounded. For the string type, it limits the number of characters that should be output, after which the string is truncated.
The precision field may be omitted, or a numeric integer value, or a dynamic value when passed as another argument when indicated by an asterisk *
. For example, printf("%.*s", 3, "abcdef")
will result in abc
being printed.
Length field[edit]
The Length field can be omitted or be any of:
Character | Description |
---|---|
hh | For integer types, causes printf to expect an int-sized integer argument which was promoted from a char. |
h | For integer types, causes printf to expect an int-sized integer argument which was promoted from a short. |
l | For integer types, causes printf to expect a long-sized integer argument.
For floating-point types, this is ignored. float arguments are always promoted to double when used in a varargs call.[4] |
ll | For integer types, causes printf to expect a long long-sized integer argument. |
L | For floating-point types, causes printf to expect a long double argument. |
z | For integer types, causes printf to expect a size_t-sized integer argument. |
j | For integer types, causes printf to expect a intmax_t-sized integer argument. |
t | For integer types, causes printf to expect a ptrdiff_t-sized integer argument. |
Additionally, several platform-specific length options came to exist prior to widespread use of the ISO C99 extensions:
Characters | Description |
---|---|
I | For signed integer types, causes printf to expect ptrdiff_t-sized integer argument; for unsigned integer types, causes printf to expect size_t-sized integer argument. Commonly found in Win32/Win64 platforms. |
I32 | For integer types, causes printf to expect a 32-bit (double word) integer argument. Commonly found in Win32/Win64 platforms. |
I64 | For integer types, causes printf to expect a 64-bit (quad word) integer argument. Commonly found in Win32/Win64 platforms. |
q | For integer types, causes printf to expect a 64-bit (quad word) integer argument. Commonly found in BSD platforms. |
ISO C99 includes the inttypes.h
header file that includes a number of macros for use in platform-independent printf
coding. These must be outside double-quotes, e.g. printf("%" PRId64 "n", t);
Example macros include:
Macro | Description |
---|---|
PRId32 | Typically equivalent to I32d (Win32/Win64) or d |
PRId64 | Typically equivalent to I64d (Win32/Win64), lld (32-bit platforms) or ld (64-bit platforms) |
PRIi32 | Typically equivalent to I32i (Win32/Win64) or i |
PRIi64 | Typically equivalent to I64i (Win32/Win64), lli (32-bit platforms) or li (64-bit platforms) |
PRIu32 | Typically equivalent to I32u (Win32/Win64) or u |
PRIu64 | Typically equivalent to I64u (Win32/Win64), llu (32-bit platforms) or lu (64-bit platforms) |
PRIx32 | Typically equivalent to I32x (Win32/Win64) or x |
PRIx64 | Typically equivalent to I64x (Win32/Win64), llx (32-bit platforms) or lx (64-bit platforms) |
Type field[edit]
The Type field can be any of:
Character | Description |
---|---|
% | Prints a literal % character (this type doesn’t accept any flags, width, precision, length fields). |
d, i | int as a signed integer. %d and %i are synonymous for output, but are different when used with scanf for input (where using %i will interpret a number as hexadecimal if it’s preceded by 0x, and octal if it’s preceded by 0.)
|
u | Print decimal unsigned int. |
f, F | double in normal (fixed-point) notation. f and F only differs in how the strings for an infinite number or NaN are printed (inf, infinity and nan for f; INF, INFINITY and NAN for F). |
e, E | double value in standard form (d.ddde±dd). An E conversion uses the letter E (rather than e) to introduce the exponent. The exponent always contains at least two digits; if the value is zero, the exponent is 00. In Windows, the exponent contains three digits by default, e.g. 1.5e002, but this can be altered by Microsoft-specific _set_output_format function.
|
g, G | double in either normal or exponential notation, whichever is more appropriate for its magnitude. g uses lower-case letters, G uses upper-case letters. This type differs slightly from fixed-point notation in that insignificant zeroes to the right of the decimal point are not included. Also, the decimal point is not included on whole numbers. |
x, X | unsigned int as a hexadecimal number. x uses lower-case letters and X uses upper-case. |
o | unsigned int in octal. |
s | null-terminated string. |
c | char (character). |
p | void* (pointer to void) in an implementation-defined format. |
a, A | double in hexadecimal notation, starting with 0x or 0X. a uses lower-case letters, A uses upper-case letters.[5][6] (C++11 iostreams have a hexfloat that works the same). |
n | Print nothing, but writes the number of characters written so far into an integer pointer parameter. In Java this prints a newline.[7] |
Custom format placeholders[edit]
There are a few implementations of printf
-like functions that allow extensions to the escape-character-based mini-language, thus allowing the programmer to have a specific formatting function for non-builtin types. One of the most well-known is the (now deprecated) glibc’s register_printf_function()
. However, it is rarely used due to the fact that it conflicts with static format string checking. Another is Vstr custom formatters, which allows adding multi-character format names.
Some applications (like the Apache HTTP Server) include their own printf
-like function, and embed extensions into it. However these all tend to have the same problems that register_printf_function()
has.
The Linux kernel printk
function supports a number of ways to display kernel structures using the generic %p
specification, by appending additional format characters.[8] For example, %pI4
prints an IPv4 address in dotted-decimal form. This allows static format string checking (of the %p
portion) at the expense of full compatibility with normal printf.
Most languages that have a printf
-like function work around the lack of this feature by just using the %s
format and converting the object to a string representation.
Vulnerabilities[edit]
Invalid conversion specifications[edit]
If there are too few function arguments provided to supply values for all the conversion specifications in the template string, or if the arguments are not of the correct types, the results are undefined, may crash. Implementations are inconsistent about whether syntax errors in the string consume an argument and what type of argument they consume. Excess arguments are ignored. In a number of cases, the undefined behavior has led to «Format string attack» security vulnerabilities. In most C or C++ calling conventions arguments may be passed on the stack, which means in the case of too few arguments printf will read past the end of the current stackframe, thus allowing the attacker to read the stack.
Some compilers, like the GNU Compiler Collection, will statically check the format strings of printf-like functions and warn about problems (when using the flags -Wall
or -Wformat
). GCC will also warn about user-defined printf-style functions if the non-standard «format» __attribute__
is applied to the function.
Field width versus explicit delimiters in tabular output[edit]
Using only field widths to provide for tabulation, as with a format like %8d%8d%8d
for three integers in three 8-character columns, will not guarantee that field separation will be retained if large numbers occur in the data:
1234567 1234567 1234567 123 123 123 123 12345678123
Loss of field separation can easily lead to corrupt output. In systems which encourage the use of programs as building blocks in scripts, such corrupt data can often be forwarded into and corrupt further processing, regardless of whether the original programmer expected the output would only be read by human eyes. Such problems can be eliminated by including explicit delimiters, even spaces, in all tabular output formats. Simply changing the dangerous example from before to %7d %7d %7d
addresses this, formatting identically until numbers become larger, but then explicitly preventing them from becoming merged on output due to the explicitly included spaces:
1234567 1234567 1234567 123 123 123 123 12345678 123
Similar strategies apply to string data.
Memory write[edit]
Although an outputting function on the surface, printf
allows writing to a memory location specified by an argument via %n
. This functionality is occasionally used as a part of more elaborate format-string attacks.[9]
The %n
functionality also makes printf
accidentally Turing-complete even with a well-formed set of arguments. A game of tic-tac-toe written in the format string is a winner of the 27th IOCCC.[10]
Programming languages with printf[edit]
Not included in this list are languages that use format strings that deviate from the style in this article (such as AMPL and Elixir), languages that inherit their implementation from the JVM or other environment (such as Clojure and Scala), and languages that do not have a standard native printf implementation but have external libraries which emulate printf behavior (such as JavaScript).
- awk[11]
- C
- C++ (also provides overloaded shift operators and manipulators as an alternative for formatted output – see iostream and iomanip)
- Objective-C
- D
- F#
- G (LabVIEW)
- GNU MathProg
- GNU Octave
- Go
- Haskell
- J
- Java (since version 1.5) and JVM languages
- Julia (via its Printf standard library;[12] Formatting.jl library adds Python-style general formatting and «c-style part of this package aims to get around the limitation that @sprintf has to take a literal string argument.»)
- Lua (string.format)
- Maple
- MATLAB
- Max (via the sprintf object)
- Mythryl
- PARI/GP
- Perl
- PHP
- Python (via
%
operator)[13] - R
- Raku (via
printf
,sprintf
, andfmt
) - Red/System
- Ruby
- Tcl (via format command)
- Transact-SQL (via xp_sprintf)
- Vala (via
print()
andFileStream.printf()
) - The
printf
utility command, sometimes built in to the shell, such as with some implementations of the KornShell (ksh), Bourne again shell (bash), or Z shell (zsh). These commands usually interpret C escapes in the format string.
See also[edit]
- Format (Common Lisp)
- C standard library
- Format string attack
iostream
- ML (programming language)
- printf debugging
printf
(Unix)printk
(print kernel messages)scanf
- string interpolation
References[edit]
- ^ «BCPL». cl.cam.ac.uk. Retrieved 19 March 2018.
- ^ McIlroy, M. D. (1987). A Research Unix reader: annotated excerpts from the Programmer’s Manual, 1971–1986 (PDF) (Technical report). CSTR. Bell Labs. 139.
- ^ «printf». cplusplus.com. Retrieved 10 June 2020.
- ^ ISO/IEC (1999). ISO/IEC 9899:1999(E): Programming Languages – C §7.19.6.1 para 7.
- ^ ««The GNU C Library Reference Manual», «12.12.3 Table of Output Conversions»«. Gnu.org. Retrieved 17 March 2014.
- ^
«printf»
(%a added in C99) - ^ «Formatting Numeric Print Output». The Java Tutorials. Oracle Inc. Retrieved 19 March 2018.
- ^ «Linux kernel Documentation/printk-formats.txt». Git.kernel.org. Retrieved 17 March 2014.
- ^ https://www.exploit-db.com/docs/english/28476-linux-format-string-exploitation.pdf[bare URL PDF]
- ^ «Best of show – abuse of libc». Ioccc.org. Retrieved 5 May 2022.
- ^ ««The Open Group Base Specifications Issue 7, 2018 edition», «POSIX awk», «Output Statements»«. pubs.opengroup.org. Retrieved 29 May 2022.
- ^ «Printf Standard Library». The Julia Language Manual. Retrieved 22 February 2021.
- ^ «Built-in Types:
printf
-style String Formatting», The Python Standard Library, Python Software Foundation, retrieved 24 February 2021
External links[edit]
- C++ reference for
std::fprintf
- gcc printf format specifications quick reference
printf
: print formatted output – System Interfaces Reference, The Single UNIX Specification, Version 4 from The Open Group- The
Formatter
specification in Java 1.5 - GNU Bash
printf(1)
builtin