Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ modulo returning inconsistent results

Tags:

c++

modulo

Can someone tell me why these two functions return different results?

After running code

#include <string>
#include <stdio.h>
#include <iostream>
using namespace std;

int returnN(string s, int n)
{
    int newN = n % s.size();
    return newN;
}

int returnN2(string s, int n)
{
    int a = s.size();
    int newN = n % a;
    return newN;
}

int main(void)
{
    string text2 = "Hello World!";
    cout << returnN(text2, -2) << endl;
    string text3 = "Hello World!";
    cout << returnN2(text3, -2) << endl;
}

returnN(text2, -2) returns 2

returnN2(text3, -2) returns -2

PS D:\src\cpp> g++ --version
g++.exe (Rev3, Built by MSYS2 project) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I tried to debug and see why but I still cant figure out why

like image 609
aloysiustanrs Avatar asked May 16 '26 01:05

aloysiustanrs


1 Answers

Can someone tell me why these two functions return different results?

s.size() returns a size_t which is unsigned.

The difference between returnN and returnN2 is in the types of the operands used for the modulo calculation:

  1. In returnN you performs a modulo with an unsigned value (s.size()).
    This means that the value of n is converted to unsigned as well to perform the modulo.
    The result of the conversion is implementation defined, but should be equal to the max value of size_t minus 1, i.e. a very large positive value.
    The modulo of this large postive value with s.size() turns out to be 2.
  2. In returnN2 you first assign s.size() to int a (which is signed), and then perform the modulo with the signed values.
    The value of n stays as is (-2), and the result is -2.

Your compiler should alert you about the issue.
MSVC for example issues the following warning for initializing a:

warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data

A side note:
It's better to avoid using namespace std; - see What's the problem with "using namespace std;"?.

like image 67
wohlstad Avatar answered May 18 '26 15:05

wohlstad