|
Before I got your reply I did a little more investigating into the issue. I was looking at the bitwise representation which I noticed is 2C as you said.
I wrote this small program to test it out. Here is the output:
11111111111111111111111111111111
11111111111111111111111111111111
(int)uint_neg_1;
11111111111111111111111111111111
int_neg_1 : %d: -1, %u: 4294967295
uint_neg_1: %d: -1, %u: 4294967295
(int)uint_neg_1: %d: -1, %u: 4294967295
int_neg_1 < 0: True
uint_neg_1 < 0: False
(int)uint_neg_1 < 0: True
So it seems that the bitwise storage and representation for signed and unsigned integers is the same.
The typecast to int changed the evaluation of the expression. I'd like to see / understand the difference in the assembly instructions because I think that is probably where the paths diverge.
Quote: There is hence absolutely no point in testing an unsigned integer for being negative! It has no capacity of being negative!
That's what I believed, but based on my experiment it's not safe to rely on the "unsigned" type as an indication of being >= 0.
If someone invokes my function with "-1" and it is written without the bounds check, the result is an access violation. As a design practice my code should catch the error of the caller.
I have a bad headache, I apologize if I've made mistakes.
See this post for the use case of an unsigned int < 0 check:
Re: (C) Robust code Should an unsigned int array index be tested for "< 0" - C / C++ / MFC Discussion Boards[^]
#include <stdio.h>
#define print_binary(a) \
for(j = 31; j >= 0; j--) \
printf("%c", a & (1 << j) ? '1' : '0'); \
printf("\n\n");
void main()
{
int j;
int int_neg_1 = -1;
unsigned int uint_neg_1 = -1;
printf("int int_neg_1 = -1;\n");
print_binary(int_neg_1);
printf("unsigned int uint_neg_1 = -1;\n");
print_binary(uint_neg_1);
printf("(int)uint_neg_1;\n");
print_binary((int)uint_neg_1);
printf("int_neg_1 : %%d: %d, %%u: %u\n", int_neg_1, int_neg_1);
printf("uint_neg_1: %%d: %d, %%u: %u\n", uint_neg_1, uint_neg_1);
printf("(int)uint_neg_1: %%d: %d, %%u: %u\n\n", (int)uint_neg_1, (int)uint_neg_1);
printf("int_neg_1\t< 0: %s\n", int_neg_1 < 0 ? "True" : "False");
printf("uint_neg_1\t< 0: %s\n\n", uint_neg_1 < 0 ? "True" : "False");
printf("(int)uint_neg_1\t< 0: %s\n\n", (int)uint_neg_1 < 0 ? "True" : "False");
}
|
|
|
|
|
Member 14088880 wrote: And that is correct. An unsigned number can only have positive values in the range 0 to infinity. The main point here is that you must follow the rules of mathematics and logic. If you declare a numeric variable as unsigned then that is how it will be treated, and it will never be considered to have a negative value (even if it does have the sign bit set). The compiler will add code to manipulate the value in such a way that any 'negativeness' is always ignored.
|
|
|
|
|
It seems like in this signed/unsigned case typecasting allows you to change the way the variable is evaluated in expressions. I think that is typical of typecasting in general, it changes interpretation.
On the other hand I think if you typecast to a data type with a different size it does not just affect the expression but also the raw value.
Please see my newest reply to the main topic.
Thanks
|
|
|
|
|
Exactly so. When you use a cast on any variable you are effectively telling the compiler to ignore the rules, as you know what you are doing, even if it is against the rules.
|
|
|
|
|
I wrote a small demonstration of the issue. Peter and Paul are writing ticketing system software and Peter makes a mistake swapping two variables and creating a negative number which is passed as an unsigned integer to Paul.
Paul makes a mistake thinking an unsigned int will not cause an out of (lower) bounds array access if it passes the test "index >= 0".
Peter makes a mistake, Paul fails to catch it, the memory is potentially corrupted and undefined behavior results. That's the PRINCIPLE the code is meant to demonstrate, which is the only purpose of this code.
As an alternative I put in a boundary check based on the address the index would have us access and the addresses of the first and last members of the array. I think that's a better approach. It should match the way the array is accessed exactly and it should be completely independent of variable size, type, typecasting, and bitwise representation.
As an aside, VS on the maximum warning level does not warn for the ints passed to the function that was declared with unsigned ints. Also, the compiler can't foresee that a negative value will be passed to the function because the sign of that variable is determined at run time.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int get_available_seat_count(unsigned int *seating_counts, unsigned int row_index, unsigned int num_rows, unsigned int seats_per_row)
{
if(row_index < 0)
{
printf("row_index < 0: TRUE\n");
return -1;
}
else
printf("row_index < 0: FALSE\n");
if(&seating_counts[row_index] < &seating_counts[0])
printf("Array minimum boundary violation, index is %d\n", row_index);
if(&seating_counts[row_index] > &seating_counts[num_rows-1])
printf("Array maximum boundary violation, index is %d\n", row_index);
return seats_per_row - seating_counts[row_index];
}
void main()
{
int num_rows = 12;
int seats_per_row = 40;
int n_available_seats;
int row_index;
unsigned int seating_counts[12];
int i;
srand((int)time(NULL));
for(i = 0; i < num_rows; i++)
seating_counts[i] = (unsigned int)rand() % seats_per_row;
printf("Customer: are there any seats available in the third row from the stage?\n\n");
row_index = 3;
n_available_seats = get_available_seat_count(seating_counts, row_index - num_rows, num_rows, seats_per_row);
printf("\nTeller: there are %d seats available in that row\n", n_available_seats);
}
Quote: Customer: are there any seats available in the third row from the stage?
row_index < 0: FALSE
Array minimum boundary violation, index is -9
Teller: there are 858993500 seats available in that row
|
|
|
|
|
But row_index is declared as unsigned int so, as I have already explained, it can never be less than zero.
|
|
|
|
|
I haven't read all of the responses in detail, so excuse me if some of the below has already be mentioned.
1. If the function argument is defined as unsigned, a signed int will be silently transformed into an unsigned leading to potentially inappropriate behavior from the viewpoint of the caller (already mentioned). The main issue here is the silent transformation that may at best be indicated as a warning at compile time. For that reason, it might be worth considering to change the argument type to signed. Some of the big guys in C++ programming think that the use of unsigned is often not worth the hassle and may convey a false sense of security. Point in case: if you have a variable of type array index, it's true that a negative value doesn't make sense. But defining it unsigned still doesn't make it range-safe as you still need to check the upper bound. Being unsigned safes you one check, but introduces the new problem of silent signed to unsigned conversions. In the end you gain nothing.
2. The test <0 always returns true on an unsigned variable. Therefore there is no point to make it. If you want to make a two-sided bounds check on an unsigned, checking just the upper bound actually treats both, because negative values will be converted to very large positive values!
3. regarding #3: don't worry about possible future extensions! Make your code look reasonable and meaningful from the point of view of the requirements that you have now! Chances are, that any future requirement will look different than you're anticipating. Furthermore, if anything problematic of a scope you're describing here is going to happen, a lot more than your function will be affected, and it's quite possible someone will come up with some generic workaround that can cope with this problem; however, if you make your code try to anticipate that change, the generic code may not work on it, because it doesn't look as expected! Better just design your code in the most reasonable way now!
4. You can avoid a lot of these problems if you simply use std::array
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
|
This may be silly to some , but I have to ask.
If the class function / method "works on" class variable should such variable value be passed to the function(class variable) or just defined / assigned outside function(void) / method?
Would assigning it outside the function defeat the "scope" of the class?
Cheers
Vaclav
|
|
|
|
|
That all depends on what the purpose of the function is, and whether the variable needs to be visible outside the function, and/or outside the class object.
|
|
|
|
|
Generally speaking, a class variable (a static variable of a class) should not (like an ordinary member variable) directly accessed by the external world, that would go against information hiding.
Moreover, you don't need need (and you should not) to pass such variables either to class (static) methods or standard (instance) methods.
|
|
|
|
|
I probably did not make myself clear in my post.
I have a class function / method which manipulates class variable - so how do I make such variable "variable" ? Simple example - if I have need to execute "switch" by varying it. I can either change the class variable or pass the value to a function.
|
|
|
|
|
I don't get you. Maybe I need more caffeine or a code sample.
|
|
|
|
|
Vaclav_ wrote:
Would assigning it outside the function defeat the "scope" of the class? The term "scope" is only meaningful to places where your class object is used (i.e., the owners of class instances). What a class does internally, on its own member variables, is not important to "outsiders."
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Generally, if you define a member variable of a class, this variable should only be accessed by member functions of that class (or derived class). This is true both for static and non-static member variables.
If you need to read or change them from outside the class, define accessor member functions as needed.
Any static or non-static function can and may access any member variable. Therefore there is no need to pass it to such a function, unless it is a non-static member variable of a different instance of the class.
Example:
class Vector3i {
private:
std::array<int,3> data;
public:
void fill(const int value) {
data.fill(value);
}
void swap(Vector3i& other) {
std::swap(data, other.data);
}
};
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
I changed the icon and put the following code in
HICON icon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
SetIcon(icon, FALSE);
in
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
and yet I still have the MFC icon when the Windows is minimized in the task bar
Thanks
|
|
|
|
|
Did you change the .ico file in the res folder?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
In Visual Studio I open up the .ico FILE (which is in the res folder) I erase what there and selecting the TEXT tool I type what I want do a save. However when I go into file explorer it still appear as the original MFC icon/bitmap
|
|
|
|
|
Sounds like you are only changing one resolution.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
I was able to modify the first 8 resolutions but for the last 5 the drawing tool bar gets grayed out
|
|
|
|
|
My task is to modify selected bits in 8 bit (char) words.
At present I have declared an array of two words.
The array gets "filled" from hardware source - I2C adapter.
I can manage to manipulate required bits using plain Boolean code - KISS.
I have found this template class " bitset " .
I have never used a template class and not sure if using it would be less code or confusion.
Since I need to pass the char pointer of the array I am not sure if changing to template class would be as obvious as passing a char array pointer.
I am open to suggestions.
Cheers
|
|
|
|
|
The problem with a bitset is that you have no control over the internal representation of the bits.
- There is no way to know whether the representation is 1 bit/value or 1 byte/value (this is a quality of implementation issue)
- There is no way to know whether the underlying type is an array of chars, ints, or some other type
- There is no way to know whether bit 0 is the MSB or the LSB of the underlying type
If you are getting data from an external source, the only safe (and portable) way to read the data is as an array of char / unsigned char. Note that std::vector<> and std::array<> guarantee that the allocated memory will be contiguous, so a pointer to the zeroth element of either would be OK as well.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
I suspect what you want to use is bit-field struct members.
e.g. your device sends you 2 bytes, formatted as follows
1-2 op status code 1
3-6 op status code 2
7-12 error code
13-16 unused
You could model that as follows
struct op_status {
unsigned int status_1:2;
unsigned int status_2:2;
unsigned int error:6;
};
If you are unfamiliar with this construct a struct member like unsigned int item:2 defines a member only 2 bits wide. The type of a bit-field member should be integral, (e.g. char, short, int, etc) but can be signed or unsigned as needed.
You can use the struct members as short ints e.g
int devfd = open("/dev/a_device", O_RDWR);
struct op_status i2c_status;
read(devfd, &i2c_status, sizeof(i2c_status));
if(i2c_status.status_1 == 1) {
} else if ( i2c_status.status_1 == 2 && i2c_status.status_2 = 1) {
switch(i2c_status.error) {
case 1:
break;
case 2:
break;
...
default:
}
}
looking a <bitset>, I don't see a nice way to group the bits together to treat them as a single unit, like you can using bit-fields. Usually, bit-fields are packed together, but check your compiler documentation to make sure. Also, don't forget that bit and/or byte order coming from your device might not match your CPU, so you may need to declare various fields out-of-order with respect to the documentation.
|
|
|
|
|
k5054 wrote: looking a <bitset>, I don't see a nice way to group the bits together to treat them as a single unit, like you can using bit-fields.
All the usual logical and shift operators are defined on bitsets. You can also convert a bitset to an integer type, and construct a bitset from an integer type. The major issue is the internal representation, which is implementation-defined. This is why a bitset should not be used to interface to hardware.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Thanks,
this will definitely give me a good start in using bitset, specially when I need to process more than two characters. Appreciate it.
At current I have this code to process single char.
cout << " data 0x" << hex << +data << endl;
data <<= iLSbit;
cout << " shifted data 0x" << hex << +data << endl;
int iDataBit;
for (int iBit = iLSbit; iBit != iMSbit + 1; iBit++) {
#ifdef DEBUG
cout << "processing bit " << dec << +iBit << endl;
buf[0] &= ~(1UL << iBit); #endif
iDataBit = (data >> iBit) & 1U;
#ifdef DEBUG
cout << " iDataBit " << hex << +iDataBit << endl;
#endif
if (iDataBit) {
#ifdef DEBUG
cout << "set bit @ position " << dec << iBit << endl;
#endif
buf[0] |= (1UL << iBit);
} else {
#ifdef DEBUG
cout << "clear bit @ position " << dec << iBit << endl;
#endif
buf[0] &= ~(1UL << iBit);
}
}
Since I need to read the data (hardware register ) before modifying it , then writing it back to hardware it seems simpler than using bitset.
At present I am modifying / checking single register parameter ( A/D converter input MUX ) , but in future I like to modify all parameters in single access. I think that is where bitset will do the job.
Thanks again
Cheers
Vaclav
|
|
|
|
|