Meaning of "size_t cnt" in library prototype - sizeof

Given the prototype:
unsigned int NI488CC ibwrt (int ud, const void * buf, size_t cnt);
What is "6L" in the function call:
ibwrt(Dev, "*IDN?\n", 6L);
Have I forgotten some very basic C stuff?

L stands for 'long' literal value. See integer-literal:
integer-suffix, if provided, may contain one or both of the following (if both are provided, they may appear in any order:
unsigned-suffix (the character u or the character U)
long-suffix (the character l or the character L) or the long-long-suffix (the character sequence ll or the character sequence LL) (since C++11)

std::size_t is the unsigned integer type of the result of the sizeof operator.
Although the type is guaranteed to be unsigned, it is still implementation defined.
Using l or L is an integer literal for long.
For example. In the following code:
auto x = 6L;
auto y = 6;
x will be of type long while y will be of type y.
Using L when passing a std::size_t is not required.
Due to Integral promotion and the unlikelyhood of competing function overloads, passing 6L is superfluous. Passing 6 would suffice.

Related

Type deduction of numeric literal to unsigned type

I was trying to compile a simple expresion which boils down to
myClass* object = new myClass();
std::vector<someType> SomeContainer;
auto N = (object) ? object->GetN() : 0; //GetN() returns <uint16_t>
assert( SomeContainer.size() == N ); // error, comparing signed to unsigned
I get that this happens, since
rank(uint16_t)=rank(unsigned short int)<rank(int)=rank(0)
such that uint16_t is promoted to int in the ?: operator, and N also becomes an int. Thus, I could solve this issue by either of the following lines
auto N = (object) ? object->GetN() : 0u; //promotion of <uint16_t> to <uint>, N is <uint>
auto N = (object) ? object->GetN() : static_cast<uint16_t>(0); //no promotion, N is <uint16_t>
auto N = (object) ? static_cast<size_t>(object->GetN()) : 0; //promotion of <uint16_t> to <size_t>, N is <size_t>
So either I use a "too large" type for one of the arguments, or I have to use the static_cast on 0, which doesn't seem very elegant to me. I do not really understand, why the treatment of the literal 0 is that counterintuitive, it really spoils the usage of auto in this case.
Shouldn't you expect N to have an unsigned type (or even specifically that of GetN())? Which solution should be preferred, or is there no elegant solution?
Notably, making N const does not help, as it would in:
size_t a=0;
auto N=0;
const auto k_N=0;
assert(a==N); // error, comparing signed to unsigned
assert(a==k_N); // true;
So shouldn't
const auto N = (object) ? object->GetN() : 0;
also result in an unsigned type, since N is never negative?
Edit: Compiler is GCC 7.3.1. Happens only in debug build.
If you want to avoid any unwanted type conversions both now and in the future, then you could force the ternary conditional operator to behave itself with
object ? object->GetN() : static_cast<decltype(object->GetN())>(0)
Although long-winded, you are at least not hardcoding the types, and the type of this expression will be the type of object->GetN(). (Note that object->GetN() is not evaluated in the decltype - there is no undefined behaviour here.)
Note that 0 is always an octal literal of type int. On a platform with a 16 bit int, it would have been promoted to an unsigned int; likely (though not guaranteed) to be the same type as std::uint16_t.

Where could I find all the C++ decimal type indicator?

Where could I find all the C++ decimal type indicator such as
long l = 0L;
I also know L U f d. Are there any others? Where can I find them all? How do I explicitly indicate an unsigned short?
This indicator you refer to is called a suffix.
For integer types, there are two types of suffixes:
unsigned-suffix — the character u or the character U
long-suffix — the character l or the character L or the long-long-suffix — the character sequence ll or the character sequence LL.
For integer literals, you can combine these suffixes, such as ul or ull to achieve both "unsignednes" and "longness" in the same literal.
There are also suffixes for floating point types: one of f, F, l, or L
Without suffix a literal defines double
f or F defines float
l or L defines long double
There are also user-defined literals, for which you can introduce user-defined suffixes.
As for your second question about unsigned short: there is no explicit suffix for short, so you will have to use static_cast or C-style cast.
Another way to do it is to define a user-defined literal operator like this
unsigned short operator "" _ush(unsigned long long int a)
{
return static_cast<unsigned short>(a);
}
And then use it to define literals like this: unsigned short a = 123_ush;
I've checked that it works using this snippet:
#include <iostream>
#include <string>
#include <typeinfo>
unsigned short operator "" _ush(unsigned long long int a)
{
return static_cast<unsigned short>(a);
}
int main()
{
std::string name;
bool equal = typeid(decltype(123_ush)) == typeid(unsigned short); // check that literal is indeed unsigned short
std::cout << equal;
}
For more info on things mentioned in my answer, I would suggest checking out cppreference: Integer literals, Floating point literal, User-defined literal
You can't. There is no such thing as an unsigned short or short literal in C++.
You need to use a static_cast.
Reference: https://en.cppreference.com/w/cpp/language/integer_literal
a short list is :
1.0 => double
1.0f => float
1 => int
1U => unsigned int
1L => long
1UL => unsigned long
1ULL => unsigned long long
1LL => long long
here is a good documentation for both prefixes and suffixes:
https://www.geeksforgeeks.org/integer-literal-in-c-cpp-prefixes-suffixes/
You can find the full list of inbuilt literal affixes in lex.literal.
I would cite the full table but we don't have markdown support for this, so here is a list of suffixes:
Integer suffixes from lex.icon/2:
(no suffix)
u or U
l or L
Both u or U and l or L
ll or LL
Both u or U and ll or LL
Which exact type these denote depends on the magnitude of the literal value, but if you look into table 7, you will find that there are no suffixes that will give you an unsigned short out of the box.
For completeness, here are the floating point suffixes from lex.fcon:
Any one of f, l, F, L.
f/F indicate float, l/L indicate long double. No suffix means double.

sizeof is used to calculate the size of any datatype, measured in the number of bytes. Doesn't it mean that number of bytes is an integer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
A riddle (in C)
see this code
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= TOTAL_ELEMENTS-2;d++)
printf("%d\n",array[d+1]);
return 0;
}
now this loop won't run.
sizeof() would return an unsigned value so TOTAL_ELEMENTS has an unsigned value.
now , coming to the for loop, please tell me if the unary operator '-' works on signed int 2 or an implicit conversion takes place into unsigned and then the '-' operator works.
In your example d is converted to an unsigned int in the comparison. But -1 cannot be represented as an unsigned int value, so it is is converted to UINT_ MAX. To avoid this behaviour you can convert the right side of the comparison to an signed int by prepending (int).
See Understand integer conversion rules for details on integer conversion in C.
There's no unary operator in d <= TOTAL_ELEMENTS-2.
The TOTAL_ELEMENTS-2 reduces to an expression with a binary operator of -. This expression then becomes unsigned because one of its operands is unsigned.
In the case of d <= TOTAL_ELEMENTS-2, d's type is also converted to unsigned int for the same reason.
The relevant portion of the standard is section 6.3.1.8#1 (ISO/IEC 9899:1999) which says:
"Otherwise, if the operand that has unsigned integer type has rank greater or
equal to the rank of the type of the other operand, then the operand with
signed integer type is converted to the type of the operand with unsigned
integer type."
Yes, d also has an unsigned type in that expression, because of promotion, which is why the loop fails.
However, the question is whether the C compiler "thinks":
(unsigned) ((unsigned) 5 - (unsigned) 2)
i.e. promoting 2 to unsigned, or:
(unsigned) ((unsigned) 5 - (signed) 2)
i.e. subtraction taking operands of both types. Of course, it doesn't matter, as it would be the same operation for both. However, the whole point is that subtracting will return a value of one type, so theoretically it can only take arguments of that type. So it's the first (unsigned int 2).
P.S. (-2) is unary, while (5 - 2) is binary.
I suspect the unsigned type of sizeof() to propagate to the expression TOTAL_ELEMENTS-2 and then to both operands of d <= TOTAL_ELEMENTS-2. Inserting (int) juste before TOTAL_ELEMENTS fixes the issue.
look , that '-' operator being unary was a stupid thing.forget it.it was the binary '-' , i realise.
when 2 is converted to unsigned int it becomes unsigned 2 , so TOTAL_ELEMENTS-2 has a value equal to unsigned 5 , and then when d is being converted to an unsigned int it gets a large positive value and
so the loop fails.
is that happening here??
and yes, i didn't write this code,this is some c puzzle i found on the web.
thank ya all.

How to make a similar cast like 1LL with any other type?

Does this make any sense?
static_cast<long long>(1) == 1LL
static_cast<float>(1) =? 1F
Is there a short way of making the casting for other types such as float?
Thank you very much!
Since C++11 you could define your own literals. For example, you could define literal _F like this:
float operator"" _F(unsigned long long l)
{
return static_cast<float>(l);
}
int main()
{
auto a = 1_F;
static_assert(std::is_same<decltype(a), float>::value, "Not a float");
return 0;
}
This answer describes C++11. User-defined literals, and some of the types, didn't exist in historic versions of the language.
Integer literals can end with nothing, L, LL, U, UL or ULL giving a type of int, long, long long, unsigned int, unsigned long or unsigned long long respectively. These can be in lower case if you like; and the actual type may be wider than specified if necessary to represent the value.
Floating-point literals can end with nothing, F or L giving a type of double, float or long double respectively. Again, these can be in lower case if you like.
Character and string literals can begin with nothing, u, U or L, giving a character type of char, char16_t, char32_t or wchar_t respectively. Strings can also begin with u8 to indicate a char character type with UTF-8 encoding.
You can also define your own user-defined literals to make literals of any type, if you find weird things like 123_km more readable than kilometres(123). I don't see the point of that, but someone's posted an example if you're interested.

In case of integer overflows what is the result of (unsigned int) * (int) ? unsigned or int?

In case of integer overflows what is the result of (unsigned int) * (int) ? unsigned or int? What type does the array index operator (operator[]) take for char*: int, unsigned int or something else?
I was auditing the following function, and suddenly this question arose. The function has a vulnerability at line 17.
// Create a character array and initialize it with init[]
// repeatedly. The size of this character array is specified by
// w*h.
char *function4(unsigned int w, unsigned int h, char *init)
{
char *buf;
int i;
if (w*h > 4096)
return (NULL);
buf = (char *)malloc(4096+1);
if (!buf)
return (NULL);
for (i=0; i<h; i++)
memcpy(&buf[i*w], init, w); // line 17
buf[4096] = '\0';
return buf;
}
Consider both w and h are very large unsigned integers. The multiplication at line 9 have a chance to pass the validation.
Now the problem is at line 17. Multiply int i with unsigned int w: if the result is int, it is possible that the product is negative, resulting in accessing a position that is before buf. If the result is unsigned int, the product will always be positive, resulting in accessing a position that is after buf.
It's hard to write code to justify this: int is too large. Does anyone has ideas on this?
Is there any documentation that specifies the type of the product? I have searched for it, but so far haven't found anything.
I suppose that as far as the vulnerability is concerned, whether (unsigned int) * (int) produces unsigned int or int doesn't matter, because in the compiled object file, they are just bytes. The following code works the same no matter the type of the product:
unsigned int x = 10;
int y = -10;
printf("%d\n", x * y); // print x * y in signed integer
printf("%u\n", x * y); // print x * y in unsigned integer
Therefore, it does not matter what type the multiplication returns. It matters that whether the consumer function takes int or unsigned.
The question here is not how bad the function is, or how to improve the function to make it better. The function undoubtedly has a vulnerability. The question is about the exact behavior of the function, based on the prescribed behavior from the standards.
do the w*h calculation in long long, check if bigger than MAX_UINT
EDIT : alternative : if overflown (w*h)/h != w (is this always the case ?! should be, right ?)
To answer your question: the type of an expression multiplying an int and an unsigned int will be an unsigned int in C/C++.
To answer your implied question, one decent way to deal with possible overflow in integer arithmetic is to use the "IntSafe" set of routines from Microsoft:
http://blogs.msdn.com/michael_howard/archive/2006/02/02/523392.aspx
It's available in the SDK and contains inline implementations so you can study what they're doing if you're on another platform.
Ensure that w * h doesn't overflow by limiting w and h.
The type of w*i is unsigned in your case. If I read the standard correctly, the rule is that the operands are converted to the larger type (with its signedness), or unsigned type corresponding to the signed type (which is unsigned int in your case).
However, even if it's unsigned, it doesn't prevent the wraparound (writing to memory before buf), because it might be the case (on i386 platform, it is), that p[-1] is the same as p[-1u]. Anyway, in your case, both buf[-1] and buf[big unsigned number] would be undefined behavior, so the signed/unsigned question is not that important.
Note that signed/unsigned matters in other contexts - eg. (int)(x*y/2) gives different results depending on the types of x and y, even in the absence of undefined behaviour.
I would solve your problem by checking for overflow on line 9; since 4096 is a pretty small constant and 4096*4096 doesn't overflow on most architectures (you need to check), I'd do
if (w>4096 || h>4096 || w*h > 4096)
return (NULL);
This leaves out the case when w or h are 0, you might want to check for it if needed.
In general, you could check for overflow like this:
if(w*h > 4096 || (w*h)/w!=h || (w*h)%w!=0)
In C/C++ the p[n] notation is really a shortcut to writting *(p+n), and this pointer arithmetic takes into account the sign. So p[-1] is valid and refers to the value immediately before *p.
So the sign really matters here, the result of arithmetic operator with integer follow a set of rules defined by the standard, and this is called integer promotions.
Check out this page: INT02-C. Understand integer conversion rules
2 changes make it safer:
if (w >= 4096 || h >= 4096 || w*h > 4096) return NULL;
...
unsigned i;
Note also that it's not less a bad idea to write to or read from past the buffer end. So the question is not whether iw may become negative, but whether 0 <= ih +w <= 4096 holds.
So it's not the type that matters, but the result of h*i.
For example, it doesn't make a difference whether this is (unsigned)0x80000000 or (int)0x80000000, the program will seg-fault anyway.
For C, refer to "Usual arithmetic conversions" (C99: Section 6.3.1.8, ANSI C K&R A6.5) for details on how the operands of the mathematical operators are treated.
In your example the following rules apply:
C99:
Otherwise, if the type of the operand
with signed integer type can represent
all of the values of the type of the
operand with unsigned integer type,
then the operand with unsigned integer
type is converted to the type of the
operand with signed integer type.
Otherwise, both operands are converted
to the unsigned integer type
corresponding to the type of the
operand with signed integer type.
ANSI C:
Otherwise, if either operand is unsigned int, the other is converted to unsigned int.
Why not just declare i as unsigned int? Then the problem goes away.
In any case, i*w is guaranteed to be <= 4096, as the code tests for this, so it's never going to overflow.
memcpy(&buf[iw > -1 ? iw < 4097? iw : 0 : 0], init, w);
I don't think the triple calculation of iw does degrade the perfomance)
w*h could overflow if w and/or h are sufficiently large and the following validation could pass.
9. if (w*h > 4096)
10. return (NULL);
On int , unsigned int mixed operations, int is elevated to unsigned int, in which case, a negative value of 'i' would become a large positive value. In that case
&buf[i*w]
would be accessing a out of bound value.
Unsigned arithmetic is done as modular (or wrap-around), so the product of two large unsigned ints can easily be less than 4096. The multiplication of int and unsigned int will result in an unsigned int (see section 4.5 of the C++ standard).
Therefore, given large w and a suitable value of h, you can indeed get into trouble.
Making sure integer arithmetic doesn't overflow is difficult. One easy way is to convert to floating-point and doing a floating-point multiplication, and seeing if the result is at all reasonable. As qwerty suggested, long long would be usable, if available on your implementation. (It's a common extension in C90 and C++, does exist in C99, and will be in C++0x.)
There are 3 paragraphs in the current C1X draft on calculating (UNSIGNED TYPE1) X (SIGNED TYPE2) in 6.3.1.8 Usual arithmetic coversions, N1494,
WG 14: C - Project status and milestones
Otherwise, if the operand that has unsigned integer type has rank greater or
equal to the rank of the type of the other operand, then the operand with
signed integer type is converted to the type of the operand with unsigned
integer type.
Otherwise, if the type of the operand with signed integer type can represent
all of the values of the type of the operand with unsigned integer type, then
the operand with unsigned integer type is converted to the type of the
operand with signed integer type.
Otherwise, both operands are converted to the unsigned integer type
corresponding to the type of the operand with signed integer type.
So if a is unsigned int and b is int, parsing of (a * b) should generate code (a * (unsigned int)b). Will overflow if b < 0 or a * b > UINT_MAX.
If a is unsigned int and b is long of greater size, (a * b) should generate ((long)a * (long)b). Will overflow if a * b > LONG_MAX or a * b < LONG_MIN.
If a is unsigned int and b is long of the same size, (a * b) should generate ((unsigned long)a * (unsigned long)b). Will overflow if b < 0 or a * b > ULONG_MAX.
On your second question about the type expected by "indexer", the answer appears "integer type" which allows for any (signed) integer index.
6.5.2.1 Array subscripting
Constraints
1 One of the expressions shall have type ‘‘pointer to complete object type’’, the other
expression shall have integer type, and the result has type ‘‘type’’.
Semantics
2 A postfix expression followed by an expression in square brackets [] is a subscripted
designation of an element of an array object. The definition of the subscript operator []
is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that
apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the
initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th
element of E1 (counting from zero).
It is up to the compiler to perform static analysis and warn the developer about possibility of buffer overrun when the pointer expression is an array variable and the index may be negative. Same goes about warning on possible array size overruns even when the index is positive or unsigned.
To actually answer your question, without specifying the hardware you're running on, you don't know, and in code intended to be portable, you shouldn't depend on any particular behavior.