Can semantic errors be detected by the compiler or not? If not when do the errors get detected?
As far as I know semantic errors are those errors which result from the expressions involving operators with incorrect number/type of operands.
For example:
n3=n1*n2;//n1 is开发者_JAVA技巧 integer, n2 is a string, n3 is an integer
The above statement is semantically incorrect.
But while reading C Primer Plus by Stephen Prata I found the following statement
The compiler does not detect semantic errors, because they don't violate C rules. The compiler has no way of divining your true intentions. That leaves it to you to find these kinds of errors. One way is to compare what a program does to what you expected it to do.
If not the compiler, who detects those errors?
Am I missing something?
"Semantic error" is another term for "logic error", where you literally write the wrong code. For example, writing n3=n1*n2
when really you wanted to divide -- the compiler has no way to tell that your algorithm should have divided instead of multiplying; you told it to multiply, so it does.
The error you described in your example is a type safety error, and compilers can catch that during their typechecking phase (if the language is strongly typed)
The word "semantic" is ambiguous, and you've encountered two slightly different meanings in these different contexts.
The first meaning (your code) is related to how a compiler interprets the code you type. But there are varying degrees of interpretation for this - syntax is one level, where interpretation is simply deciding that n1*n2
means you want to perform multiplication. But there is also a higher level of interpretation here - if n1
is an integer, and n2
is floating point, what is the result? What if I cast it, should it be rounded, truncated, etc? These are "semantic" questions rather than syntactic ones, but someone, somewhere, decided that yes, the compiler can answer these for most people.
They also decided that the compiler has limits to what it can (and should!) interpret. For example, it can decide that casting to an int
is a truncation, not rounding, but it can't decide what you really want when you try to multiply an array by a number.
(Sometimes people decide that they CAN, though. In Python, [1] * 3 == [1,1,1]
.)
The second meaning refers to a much wider scope. If the result of that operation is supposed to be sent to a peripheral device that can take values of 0x000 to 0xFFF, and you multiply 0x7FF by 0x010, clearly you've made a semantic error. The designers of the peripheral device must decide whether, or how, to cope with that. You, as a programmer, could also decide to put in some sanity checks. But the compiler has no idea about these external semantic constraints, or how to enforce them (filter user input? return an error? truncate? wrap?), which is what the second quote is saying.
There are basically three types of errors.
1) Syntax errors. These are invalid code the compiler doesn't understand, e.g. your example of multiplying a string with an integer in C. The compiler will detect them, because it can't compile them.
2) Semantic errors. These are valid code the compiler understands, but they do not what you, the programmer, intended. These may be using the wrong variable, the wrong operation, or operations in the wrong order. There is no way for the compiler to detect them.
There is a third class, which can be the most expensive:
3) Design errors. The code is correct and bug-free and does exactly what you've intended. But your intentions are wrong, e.g. based on wrong assumptions, wrong models, or you've used the wrong formulars, misunderstood the customer, or such.
I think the writer who wrote the book defined "semantic" differently. For most compilers, there is a step involving some semantic checks.
Semantic analysis is the phase in which the compiler adds semantic information to the parse tree and builds the symbol table. This phase performs semantic checks such as type checking (checking for type errors), or object binding (associating variable and function references with their definitions), or definite assignment (requiring all local variables to be initialized before use), rejecting incorrect programs or issuing warnings. Semantic analysis usually requires a complete parse tree, meaning that this phase logically follows the parsing phase, and logically precedes the code generation phase, though it is often possible to fold multiple phases into one pass over the code in a compiler implementation.
Semantic errors are all those, where your code does something you didn't intend.
These errors can be caught by testing or analysis.
Analysis means you or a tool looks at your code and try to find out problems. This involves using code reviews and static analyzers.
Testing is when you give your program some inputs that are expected to produce a given output if the program is semantically correct. So If the actual output doesnt match the expected output, the program is semantically incorrect.
So simply put, it is YOU the developer or tester who is supposed to catch semantic errors.
That quote is talking about things like doing a x <= 1
where you really should have done x < 1
.
But for the semantics of the language (not being allowed to add a string and an integer), yes it is the compiler that handles that.
That is a syntactic error, which compilers can indeed detect and report.
A semantic error is more like something that compiles fine (down to the very types), but isn't what you want it to be. Semantic errors are part of your algorithm more than your actual syntax.
If not the compiler, who detects those errors?
Sometimes, no-one: the compiler does not have to insert any run-time checks that could help notice the error when it happens, and the execution just continues.
Sometimes, the execution environment: the program accesses an invalid address because of an error, and it is outside the address space that the process can legally access.
You can use complement the compiler with a static analyzer to detect some or all of the errors in a program, but these can also have false positives: they may emit a warning for a piece of code that works without errors.
Actually, multiplying a string and an integer is a syntactic error since the multiplication of incompatible types (such as a string and an integer) is not defined in C.
A semantic error is an error which occurs when your program does compile, but does not do what you want.
String literals and strings are presented in memory as numbers (bytes/m words or in high-level - shorts, integers). C is low-level programming level, in which all things are approached to machine/assembler level. So multiplication of number on string literal (if it is array, it will be incorrect) is correct, because this string literal will be actually (after compilation) a number.
Actually (as there is no string
type in C but only char*
) you can very well multiply n1
with n2
. The operation is legal and well defined, that is why the compiler will not issue an error.
Logically (semantically) the statement makes very few sense, so it is most likely a coding error. To answer your question: You are responsible for detecting and fixing these kinds of errors.
精彩评论